package com.lanchetech.user.service.impl;


import com.alibaba.fastjson.JSON;
import com.baidu.fsg.uid.UidGenerator;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.lanchetech.bean.dto.ActivityDTO;
import com.lanchetech.bean.dto.FreightDTO;
import com.lanchetech.bean.dto.HourDTO;
import com.lanchetech.bean.dto.OrderItemDTO;
import com.lanchetech.bean.request.*;
import com.lanchetech.bean.response.*;
import com.lanchetech.common.util.ObjectUtil;
import com.lanchetech.bean.redission.LockCenter;
import com.lanchetech.user.task.MiniShareDetailedTask;
import com.lanchetech.bean.util.DateConvertUtil;
import com.lanchetech.bean.util.PageHelpUtil;
import com.lanchetech.bean.vo.*;
import com.lanchetech.common.constants.BaseConstant;
import com.lanchetech.common.enums.*;
import com.lanchetech.common.exception.ResultCodeException;
import com.lanchetech.common.util.IpUtil;
import com.lanchetech.common.util.SensitiveInfoUtil;
import com.lanchetech.common.util.StringHelper;
import com.lanchetech.dao.*;
import com.lanchetech.entity.*;
import com.lanchetech.service.*;
import com.lanchetech.user.config.ReturnPayInfoVO;
import com.lanchetech.user.service.CommonService;
import com.lanchetech.user.service.OrderService;
import com.lanchetech.user.service.ShopService;
import com.lanchetech.user.service.UserService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.hashids.Hashids;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;

import static com.lanchetech.common.constants.JypConstant.MAX_AMOUNT;

@Service
public class OrderServiceImpl implements OrderService {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    WxPayService wxPayService;

    @Autowired
    SkuMapper skuMapper;

    @Autowired
    FlashSaleSkuMapper flashSaleSkuMapper;

    @Autowired
    FlashSaleActivityMapper flashSaleActivityMapper;

    @Autowired
    CoinDeductionMapper coinDeductionMapper;

    @Autowired
    FreightMapper freightMapper;

    @Autowired
    FreightListMapper freightListMapper;

    @Autowired
    OrdersMapper ordersMapper;

    @Autowired
    OrderSkuMapper orderSkuMapper;

    @Autowired
    CommonService commonService;
    @Autowired
    private UserAmtLogMapper userAmtLogMapper;

    @Autowired
    UserAddressMapper userAddressMapper;

    @Autowired
    OrderAddressMapper orderAddressMapper;

    @Value("${domain.url}")
    private String domainUrl;

    @Resource
    UidGenerator uidGenerator;

    @Autowired
    ShoppingCartMapper shoppingCartMapper;

    @Autowired
    SpuMapper spuMapper;

    @Autowired
    OrderCommentMapper orderCommentMapper;

    @Autowired
    AfterSaleMapper afterSaleMapper;

    @Autowired
    OrderDiscountMapper orderDiscountMapper;

    @Autowired
    CommentStatisticsMapper commentStatisticsMapper;

    @Autowired
    LogisticsService logisticsService;

    @Autowired
    FlashSaleSpuMapper flashSaleSpuMapper;

    @Autowired
    DaoService daoService;

    @Autowired
    PrivilegeMapper privilegeMapper;

    @Autowired
    SpuCommissionMapper spuCommissionMapper;

    @Autowired
    UserRelationshipMapper userRelationshipMapper;

    @Autowired
    UserCommissionMapper userCommissionMapper;

    @Autowired
    PackagesMapper packagesMapper;

    @Autowired
    PackageSkuMapper packageSkuMapper;

    @Autowired
    UserCouponMapper userCouponMapper;

    @Autowired
    CouponMapper couponMapper;

    @Autowired
    UserService userService;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    CoinSettingMapper coinSettingMapper;

    @Autowired
    UserMapper userMapper;

    @Autowired
    CoinRewardMapper coinRewardMapper;

    @Autowired
    UserRoleMapper userRoleMapper;

    @Autowired
    ShopMapper shopMapper;

    @Value("${order.hashid.salt}")
    private String salt;

    @Autowired
    ShopService shopService;

    @Autowired
    CommissionService commissionService;

    @Autowired
    SkuColumnCourseMapper skuColumnCourseMapper;

    @Autowired
    ColumnCourseAuthMapper columnCourseAuthMapper;

    @Autowired
    ConsumptionService consumptionService;

    @Autowired
    CoinFlowMapper coinFlowMapper;

    @Autowired
    ExpService expService;

    @Autowired
    HipoConfigMapper hipoConfigMapper;

    @Autowired
    LevelService levelService;

    @Autowired
    CardFlowMapper cardFlowMapper;

    @Autowired
    AppointmentSettingMapper appointmentSettingMapper;

    @Autowired
    UserVoucherMapper userVoucherMapper;

    @Autowired
    BossMapper bossMapper;

    @Autowired
    BargainRecordMapper bargainRecordMapper;

    @Autowired
    BargainSkuMapper bargainSkuMapper;

    @Autowired
    BargainSpuMapper bargainSpuMapper;

    @Autowired
    BargainActivityMapper bargainActivityMapper;

    @Autowired
    SecondRelationshipMapper secondRelationshipMapper;

    @Autowired
    ShopRelationshipMapper shopRelationshipMapper;

    @Autowired
    CommonFarmService commonFarmService;

    @Autowired
    SmsService smsService;

    @Autowired
    OrderPayMapper orderPayMapper;

    @Autowired
    TenantMapper tenantMapper;

    @Autowired
    TenantFlowMapper tenantFlowMapper;

    @Autowired
    ShopStatisticsMapper shopStatisticsMapper;

    @Autowired
    private Scheduler scheduler;

    @Value("${wx.pay.appId}")
    private String miniAppId;

    @Value("${wx.app.appId}")
    private String appAppId;

    @Autowired
    FinanceService financeService;

    @Autowired
    CommonOrderService commonOrderService;

    @Autowired
    QuartzService quartzService;

    @Autowired
    ShopAnnouncementMapper shopAnnouncementMapper;

    @Autowired
    AnnouncementMapper announcementMapper;

    @Autowired
    JpushService jpushService;

    @Autowired
    IdentityMapper identityMapper;

    @Autowired
    AnnouncementService announcementService;

    @Autowired
    KuaidizsService kuaidizsService;

    @Autowired
    RewardQueueMapper rewardQueueMapper;

    @Autowired
    WebConfigMapper webConfigMapper;

    @Autowired
    LotteryOpportunityMapper lotteryOpportunityMapper;

    @Autowired
    ZoneSpuMapper zoneSpuMapper;

    @Autowired
    ZoneMapper zoneMapper;

    @Autowired
    private ShareActivityMapper shareActivityMapper;
    @Autowired
    private ShareActivitySpuMapper shareActivitySpuMapper;
    @Autowired
    private ShareUserLevelMapper shareUserLevelMapper;
    @Autowired
    private ShareDetailedMapper shareDetailedMapper;
    @Autowired
    private MiniShareDetailedTask miniShareDetailedTask;
    @Autowired
    private ShareActivityService shareActivityService;
    @Autowired
    private CardConsumptionFundItemMapper cardConsumptionFundItemMapper;
    @Autowired
    private CardConsumptionUserMapper cardConsumptionUserMapper;
    @Autowired
    ActivityBindSpuMapper bindSpuMapper;
    @Autowired
    ActivityMapper activityMapper;

    private Long getUserShopId(User user) {
        return user.getShopId();
    }

    @Override
    public ResultData<List<OrderSkuItemVO>> getConfirmOrderSkuInfo(List<OrderItemDTO> req, Long userId) {
        List<OrderSkuItemVO> list = new ArrayList<>();
        // 套餐只需要获取1次
        boolean isPackages = req.size() > 0 && ActivityEnum.PACKAGES.getActivity().equals(req.get(0).getActivityType());
        HashMap<Long, PackageSku> packageSkuHashMap = new HashMap<>();
        if (isPackages) {
            // 如果是套餐，则不用去校验套餐的有效性，有效性在提交订单时校验
            List<PackageSku> packageSkuList = packageSkuMapper.findAllByActivityId(req.get(0).getActivityId());
            packageSkuList.stream().forEach((item) -> packageSkuHashMap.put(item.getSkuId(), item));
        }
        for (OrderItemDTO item : req) {
            OrderSkuItemVO orderSkuItemVO = new OrderSkuItemVO();
            Sku sku = skuMapper.selectByPrimaryKey(item.getSkuId());
            Spu spu = spuMapper.selectByPrimaryKey(sku.getSpuId());
            SkuItemVO skuItemVO = new SkuItemVO(spu.getName(), spu.getDescription(), spu.getFreightId(), spu.getShopId(), spu.getType(), spu.getHidden(), spu.getLimitCount());
            BeanUtils.copyProperties(sku, skuItemVO);
            ActivityDTO activityDTO = new ActivityDTO();

            // 活动
            if (!StringUtils.isEmpty(item.getActivityType())) {
                // 秒杀
//                if (ActivityEnum.KILL.getActivity().equals(item.getActivityType())) {
//
//                }
                // 校验消费金
                if (ActivityEnum.CONSUMPTION_FUND.getActivity().equals(item.getActivityType())) {
                    Shop shop = shopMapper.selectByPrimaryKey(skuItemVO.getTenantId());
                    // 判断用户是否为首次折扣
                    int count = orderSkuMapper.getOrderSkuByUserId(userId, ActivityEnum.CONSUMPTION_FUND.getActivity());
                    CardConsumptionFundItem oneFundItemBySupId =
                            cardConsumptionFundItemMapper.getOneFundItemBySupId(item.getActivityId(),
                                    skuItemVO.getSpuId());
                    if (oneFundItemBySupId != null) {
                        // 购买数量
                        BigDecimal itemNum = BigDecimal.valueOf(item.getCount());

                        // 抵扣金额
                        BigDecimal discount;
                        if (count == 0) {
                            discount = skuItemVO.getPrice().multiply(oneFundItemBySupId.getFirstDiscount());
                        } else {
                            discount = skuItemVO.getPrice().multiply(oneFundItemBySupId.getFollowDiscount());
                        }
                        // 抵扣金额*购买数量 = 总的折扣价格
                        BigDecimal discountPrice = discount.multiply(itemNum);
                        skuItemVO.setDiscountPrice(discountPrice);
                        // 商家扣除服务费实际获得金额   (商品总价格 - 抵扣金额) * 商家服务费 = 商户所得金额
                        skuItemVO.setCostPrice((skuItemVO.getPrice().subtract(discount)).multiply(shop.getServiceRate()));
                        activityDTO = ActivityDTO.builder()
                                .activityId(item.getActivityId())
                                .skuId(item.getSkuId())
                                .activityType(ActivityEnum.CONSUMPTION_FUND.getActivity())
                                .discountPrice(discountPrice)
                                .price(skuItemVO.getPrice())
                                .stock(skuItemVO.getStock())
                                .build();
                        orderSkuItemVO.setDiscountPrice(discountPrice);
                    }
                }
                // 限时优惠
                if (ActivityEnum.FLASH_SALE.getActivity().equals(item.getActivityType())) {
                    // 获取有效的限时优惠活动的价格
                    FlashSaleSku flashSaleSku = flashSaleSkuMapper.findOneByActivityIdAndSkuId(item.getActivityId(), item.getSkuId());
                    if (flashSaleSku != null) {
                        // 判断有效期、活动状态、获取限购数量
                        FlashSaleSpu flashSaleSpu = flashSaleSpuMapper.findOneByActivityIdAndSpuId(flashSaleSku.getActivityId(), flashSaleSku.getSpuId());
                        if (ToggleEnum.ON.getStatus().equals(flashSaleSpu.getStatus())) {
                            FlashSaleActivity flashSaleActivity = flashSaleActivityMapper.selectByPrimaryKey(flashSaleSku.getActivityId());
                            if (ToggleEnum.ON.getStatus().equals(flashSaleActivity.getStatus()) && System.currentTimeMillis() > flashSaleActivity.getStartTime().getTime() && System.currentTimeMillis() < flashSaleActivity.getEndTime().getTime()) {
                                activityDTO = ActivityDTO.builder()
                                        .activityId(item.getActivityId())
                                        .skuId(item.getSkuId())
                                        .activityType(ActivityEnum.FLASH_SALE.getActivity())
                                        .price(flashSaleSku.getPrice())
                                        .stock(flashSaleSku.getStock())
                                        .limitCount(flashSaleSpu.getLimitCount())
                                        .build();
                            }
                        }
                    }
                }
                // 砍价
                if (ActivityEnum.BARGAIN.getActivity().equals(item.getActivityType())) {
                    // 获取有效的限时优惠活动的价格
                    BargainSku bargainSku = bargainSkuMapper.findOneByActivityIdAndSkuId(item.getActivityId(), item.getSkuId());
                    if (bargainSku != null) {
                        // 判断有效期、活动状态、获取限购数量
                        BargainSpu bargainSpu = bargainSpuMapper.findOneByActivityIdAndSpuId(bargainSku.getActivityId(), bargainSku.getSpuId());
                        if (ToggleEnum.ON.getStatus().equals(bargainSpu.getStatus())) {
                            BargainActivity bargainActivity = bargainActivityMapper.selectByPrimaryKey(bargainSpu.getActivityId());
                            if (ToggleEnum.ON.getStatus().equals(bargainActivity.getStatus()) && System.currentTimeMillis() > bargainActivity.getStartTime().getTime() && System.currentTimeMillis() < bargainActivity.getEndTime().getTime()) {
                                activityDTO = ActivityDTO.builder().activityId(item.getActivityId()).skuId(item.getSkuId()).activityType(ActivityEnum.BARGAIN.getActivity()).price(bargainSku.getPrice()).stock(bargainSku.getStock()).limitCount(bargainSpu.getLimitCount()).build();
                            }
                        }
                    }
                }

                // 套餐
                if (isPackages) {
                    activityDTO = ActivityDTO.builder()
                            .activityId(item.getActivityId())
                            .skuId(item.getSkuId())
                            .activityType(ActivityEnum.PACKAGES.getActivity())
                            .price(packageSkuHashMap.get(item.getSkuId()).getPrice())
                            .stock(Integer.MAX_VALUE)
                            .limitCount(Integer.MAX_VALUE)
                            .build();
                }

                // 预约
                if (ActivityEnum.PROJECT.getActivity().equals(item.getActivityType())) {
                    activityDTO = ActivityDTO.builder().activityId(item.getActivityId())
                            .skuId(item.getSkuId())
                            .activityType(ActivityEnum.PROJECT.getActivity())
                            .price(sku.getPrice())
                            .stock(Integer.MAX_VALUE)
                            .limitCount(Integer.MAX_VALUE).build();
                }

                // 体验
                if (ActivityEnum.EXPERIENCE.getActivity().equals(item.getActivityType())) {
                    activityDTO = ActivityDTO.builder().activityId(item.getActivityId())
                            .skuId(item.getSkuId())
                            .activityType(ActivityEnum.EXPERIENCE.getActivity())
                            .price(sku.getPrice())
                            .stock(Integer.MAX_VALUE)
                            .limitCount(Integer.MAX_VALUE)
                            .build();
                }

                // 活动报名
                if (ActivityEnum.APPLY.getActivity().equals(item.getActivityType())) {
                    activityDTO = ActivityDTO.builder()
                            .activityId(item.getActivityId())
                            .skuId(item.getSkuId())
                            .activityType(ActivityEnum.APPLY.getActivity())
                            .price(sku.getPrice())
                            .stock(Integer.MAX_VALUE)
                            .limitCount(Integer.MAX_VALUE)
                            .build();
                }
            }
            orderSkuItemVO.setMiniCommissionScaleRebate(item.getMiniCommissionScaleRebate());
            orderSkuItemVO.setMiniHiCoinScaleRebate(item.getMiniHiCoinScaleRebate());
            orderSkuItemVO.setShareActivityId(item.getShareActivityId());
            orderSkuItemVO.setShare(item.isShare());
            orderSkuItemVO.setBeneficiaryUserId(item.getBeneficiaryUserId());
            orderSkuItemVO.setSku(skuItemVO);
            orderSkuItemVO.setActivity(activityDTO);
            orderSkuItemVO.setCount(item.getCount());
            orderSkuItemVO.setAppointmentTime(item.getAppointmentTime());
            orderSkuItemVO.setCoinDeduction(coinDeductionMapper.findOneActive(sku.getSpuId()));
            // 运费
            orderSkuItemVO.setFreight(freightMapper.selectByPrimaryKey(skuItemVO.getFreightId()));
            orderSkuItemVO.setFreightLists(freightListMapper.findAllByFreightId(skuItemVO.getFreightId()));
            list.add(orderSkuItemVO);
        }
        return new ResultData<>(list);
    }

    @Override
    public ResultData<ConfirmOrderResp> getConfirmOrderDetail(User user, List<OrderItemDTO> req) {
        ConfirmOrderResp resp = new ConfirmOrderResp();
        resp.setSkuList(getConfirmOrderSkuInfo(req, user.getId()).getValue());
        resp.setAddress(userService.getMainUserAddress(user).getValue());
        resp.setPartnerSpuId(daoService.getHipoConfigValue(HipoConfigEnum.PARTNER_SPU.getConfig()));
        resp.setMemberSpuId(daoService.getHipoConfigValue(HipoConfigEnum.MEMBER_SPU.getConfig()));
        resp.setShareholderSpuId(daoService.getHipoConfigValue(HipoConfigEnum.SHAREHOLDER_SPU.getConfig()));
        resp.setCompanySpuId(daoService.getHipoConfigValue(HipoConfigEnum.COMPANY_SPU.getConfig()));

        ValueOperations<String, List<CoinSetting>> operations = redisTemplate.opsForValue();
        List<CoinSetting> coinSettingList = operations.get("CoinSetting");
        if (coinSettingList != null) {
            resp.setCoinSettingList(coinSettingList);
        } else {
            coinSettingList = coinSettingMapper.findAll();
            resp.setCoinSettingList(coinSettingList);
            operations.set("CoinSetting", coinSettingList);
        }

        // 获取用户所有可以使用的优惠券
        List<UserCoupon> userCouponList = userCouponMapper.findAllByUserIdAndStatusAndNow(user.getId(), UseEnum.NOT_USE.getStatus(), new Date());
        if (!CollectionUtils.isEmpty(userCouponList)) {
            List<Coupon> couponList = couponMapper.findAllByIds(userCouponList.stream().map(UserCoupon::getCouponId).collect(Collectors.toList()));
            // 筛选出所有有效的优惠券
            List<Coupon> resultList = couponList.stream().filter(item -> ToggleEnum.ON.getStatus().equals(item.getStatus()) && DeletedEnum.DEFAULT.getStatus().equals(item.getDeleted())).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(resultList)) {
                resp.setCouponList(resultList);
            }
        }

        if (ActivityEnum.BARGAIN.getActivity().equals(req.get(0).getActivityType()) || ActivityEnum.FLASH_SALE.getActivity().equals(req.get(0).getActivityType())) {
            // 秒杀和砍价，不可以再使用兑换卡
            // 返回商店信息
            Shop shop = shopMapper.selectByPrimaryKey(resp.getSkuList().get(0).getSku().getShopId());
            resp.setShopAvatar(shop.getAvatar());
            resp.setShopName(shop.getShopName());

            if (ActivityEnum.BARGAIN.getActivity().equals(req.get(0).getActivityType())) {
                resp.setBargainRecord(bargainRecordMapper.findOneByUserIdAndSkuIdAndStatus(user.getId(), req.get(0).getSkuId(), ToggleEnum.OFF.getStatus()));
            }

        } else {
            // 获取用户当前可用的兑换券
            resp.setUserVoucher(userVoucherMapper.findOneByUserIdAndSpuIdAndStatus(user.getId(), resp.getSkuList().get(0).getSku().getSpuId(), VoucherStatusEnum.AVAILABLE.getStatus()));
        }
        Shop shop = shopMapper.selectByPrimaryKey(resp.getSkuList().get(0).getSku().getTenantId());
        resp.setTenantId(shop.getId());
        resp.setTenantNickname(shop.getShopName());
        resp.setShopType(shop.getType());
        return new ResultData<>(resp);
    }

    /**
     * 校验新人专区商品
     *
     * @param identity
     * @param orderList
     * @throws ResultCodeException
     */
    private void checkNewZoneSpu(Identity identity, List<OrderSkuItemVO> orderList) throws ResultCodeException {
        List<Long> spuIds = new ArrayList<>();
        orderList.stream().forEach(item -> {
            spuIds.add(item.getSku().getSpuId());
        });
        List<ZoneSpu> zoneSpuList = zoneSpuMapper.findAllBySpuIdInAndNewZone(spuIds, ToggleEnum.ON.getStatus());
        if (!CollectionUtils.isEmpty(zoneSpuList)) {
            Boolean newZoneBuy = false;
            Map<Long, ZoneSpu> zoneSpuMap = zoneSpuList.stream().collect(Collectors.toMap(ZoneSpu::getSpuId, ZoneSpu -> ZoneSpu));
            for (OrderSkuItemVO item : orderList) {
                if (zoneSpuMap.containsKey(item.getSku().getSpuId())) {
                    if (newZoneBuy || item.getCount() > 1) {
                        throw new ResultCodeException(ResultCode.NEW_ZONE_LIMIT1);
                    }
                    if (ToggleEnum.ON.getStatus().equals(identity.getNewZoneBuy())) {
                        throw new ResultCodeException(ResultCode.NEW_ZONE_PURCHASED);
                    }
                    if (MemberStateEnum.SUPER.getType().equals(identity.getMemberState())) {
                        throw new ResultCodeException(ResultCode.SPU_NEED_NEW_PEOPLE);
                    }
                    newZoneBuy = true;
                }
            }
        }
    }

    /**
     * 校验安全密码
     *
     * @param securityPassword
     * @param user
     * @throws ResultCodeException
     */
    private void checkSecurityPassword(String securityPassword, User user, Byte payType) throws ResultCodeException {
        if (PayTypeEnum.VIP_CARD.getType().equals(payType)) {
            if (user.getPayPassword() == null) {
                throw new ResultCodeException(ResultCode.NOT_HAS_PAY_PASSWORD);
            }
            if (!StringUtils.isEmpty(securityPassword)) {
                ValueOperations<String, Integer> operations = redisTemplate.opsForValue();
                Integer count = operations.get("PayPasswordError:" + user.getId().toString());
                if (count != null && count >= 5) {
                    throw new ResultCodeException(ResultCode.AFTER_ONE_MINUTE);
                }
                if (!new BCryptPasswordEncoder().matches(securityPassword, user.getPayPassword())) {
                    operations.set("PayPasswordError:" + user.getId(), count == null ? 1 : count + 1, 1, TimeUnit.MINUTES);
                    throw new ResultCodeException(ResultCode.PAY_PASSWORD_ERROR);
                }
            } else {
                throw new ResultCodeException(ResultCode.NEED_SECURITY_PASSWORD);
            }
        }
    }


    /**
     * 校验商品状态
     *
     * @param orderList
     * @return
     */
    private void checkStatus(List<OrderSkuItemVO> orderList) throws ResultCodeException {
        for (OrderSkuItemVO item : orderList) {
            if (DeletedEnum.DELETED.getStatus().equals(item.getSku().getDeleted())) {
                throw new ResultCodeException(ResultCode.SKU_DELETED);
            }
            if (HiddenEnum.HIDDEN.getStatus().equals(item.getSku().getHidden()) || HiddenEnum.PLATFORM_HIDDEN.getStatus().equals(item.getSku().getHidden())) {
                throw new ResultCodeException(ResultCode.SKU_HIDDEN);
            }
            // SPU被下架后就不可以购买
            if (!HiddenEnum.VISIBLE.getStatus().equals(item.getSku().getSpuHidden())) {
                throw new ResultCodeException(ResultCode.SKU_HIDDEN);
            }
        }
    }

    /**
     * 校验库存和购买数量合法性
     *
     * @param orderList
     * @return
     */
    private void checkStock(List<OrderSkuItemVO> orderList, User user, Identity identity) throws ResultCodeException {
        //当前订单内spu数量
        Map<Long, Integer> spuCountMap = new HashMap<>();
        for (OrderSkuItemVO item : orderList) {
            // 检查购买数量是否超过可售库存
            if (item.getCount() > item.getSku().getStock()) {
                throw new ResultCodeException(ResultCode.SKU_STOCK_NOT_ENOUGH);
            }

            if (item.getCount() <= 0) {
                throw new ResultCodeException(ResultCode.FAIL);
            }

            //检查限购数量
            if (item.getSku().getLimitCount() != 0L) {
                Integer spuCount = 0;
                if (spuCountMap.containsKey(item.getSku().getSpuId())) {
                    spuCount = spuCountMap.get(item.getSku().getSpuId());
                }
                spuCountMap.put(item.getSku().getSpuId(), item.getCount() + spuCount);

                Long buyCount = orderSkuMapper.sumBuyCountBySpuId(item.getSku().getSpuId(), user.getId());
                if (buyCount == null) {
                    buyCount = 0L;
                }
                if (item.getSku().getLimitCount() - buyCount < item.getCount() + spuCount) {
                    throw new ResultCodeException(ResultCode.OVER_SPU_LIMIT_COUNT);
                }
            }

            // 如果参加活动
            if (item.getActivity().getActivityType() != null) {
//                //会员才能参与秒杀活动
//                if (ActivityEnum.FLASH_SALE.getActivity().equals(item.getActivity().getActivityType())) {
//                    Boolean isMember = identity != null && MemberStateEnum.SUPER.getType().equals(identity.getMemberState()) && (identity.getMemberExpireTime() != null) && identity.getMemberExpireTime().after(new Date());
//                    if (!isMember) {
//                        throw new ResultCodeException(ResultCode.NEED_MEMBER_IDENTITY);
//                    }
//                }

                // 检查是否超过活动库存
                if (item.getCount() > item.getActivity().getStock()) {
                    throw new ResultCodeException(ResultCode.SKU_ACTIVITY_STOCK_NOT_ENOUGH);
                }

                // 如果是限时优惠，再检查是否超过限购数量
                if (ActivityEnum.FLASH_SALE.getActivity().equals(item.getActivity().getActivityType())) {
                    // 要从数据库中统计他已购的此活动的商品的数量
                    Integer totalCount = orderSkuMapper.sumAllForActivity(item.getActivity().getActivityType(), item.getActivity().getActivityId(), item.getSku().getSpuId(), user.getId());
                    if (totalCount == null) {
                        totalCount = 0;
                    }
                    // limitCount为0则表示不限购
                    if ((totalCount + item.getCount()) > item.getActivity().getLimitCount() && !item.getActivity().getLimitCount().equals(0)) {
                        throw new ResultCodeException(ResultCode.FLASH_SALE_LIMIT);
                    }
                }
            }
        }
    }

    /**
     * 校验免单合法性
     *
     * @param orderList
     * @return
     */
    private void checkFree(List<OrderSkuItemVO> orderList, Long userId) throws ResultCodeException {
        for (OrderSkuItemVO item : orderList) {
            // 如果包含免单商品
            if (SpuTypeEnum.NORMAL.getType().equals(item.getSku().getType())) {
                // 检查当前商品是否存在未免单，如果存在，则不让购买
                if (rewardQueueMapper.findOneByRewardTypeAndSpuIdAndUserIdAndRewardStatus(RewardTypeEnum.SPU.getType(), item.getSku().getSpuId(), userId, RewardQueueStatusEnum.QUEUING.getStatus()) != null) {
                    throw new ResultCodeException(ResultCode.FREE_NOT);
                }
            }
        }
    }

    /**
     * 校验价格合法性并计算最终价格
     *
     * @param orderList
     * @return
     */
    private void checkPrice(List<OrderSkuItemVO> orderList) throws ResultCodeException {
        for (OrderSkuItemVO item : orderList) {
            // 计算价格
            item.setFinalPrice(getOrderSkuPrice(item));
//            if (!ActivityEnum.FLASH_SALE.getActivity().equals(item.getActivity().getActivityType())) {
//                // 不可以低于成本价
//                if (item.getFinalPrice().compareTo(item.getSku().getCostPrice()) == -1) {
//                    throw new ResultCodeException(ResultCode.LOWER_THAN_COST_PRICE);
//                }
//            }
        }
    }

    /**
     * 校验价格合法性并计算最终价格
     *
     * @param orderList
     * @return
     */
    private void checkPriceForRushBuy(List<OrderSkuItemVO> orderList) throws ResultCodeException {
        for (OrderSkuItemVO item : orderList) {
            // 计算价格
            item.setFinalPrice(getOrderSkuPrice(item));

            // 如果是抢购商品或者合伙人商品，则打6折
            if (SpuTypeEnum.COMMISSION.getType().equals(item.getSku().getType()) || SpuTypeEnum.PARTNER.getType().equals(item.getSku().getType())) {
//                BigDecimal six = item.getSku().getPrice().multiply(new BigDecimal(0.6)).setScale(2, BigDecimal.ROUND_HALF_DOWN);
//                if (item.getFinalPrice().compareTo(six) > 0) {
//                    item.setFinalPrice(six);
//                }
                item.setFinalPrice(item.getSku().getVipPrice());
            }

//            if (!ActivityEnum.FLASH_SALE.getActivity().equals(item.getActivity().getActivityType()) && !isMemberPrice) {
//                // 不可以低于成本价
//                if (item.getFinalPrice().compareTo(item.getSku().getCostPrice()) == -1) {
//                    throw new ResultCodeException(ResultCode.LOWER_THAN_COST_PRICE);
//                }
//            }
        }
    }

    private void checkPartnerPrice(List<OrderSkuItemVO> orderList) throws ResultCodeException {
        for (OrderSkuItemVO item : orderList) {
            // 计算价格
            item.setFinalPrice(getOrderSkuPrice(item));

            if (SpuTypeEnum.PARTNER.getType().equals(item.getSku().getType()) || SpuTypeEnum.ORDINARY.getType().equals(item.getSku().getType())) {
                if (item.getFinalPrice().compareTo(item.getSku().getPartnerPrice()) > 0) {
                    item.setFinalPrice(item.getSku().getPartnerPrice());
                }
            }

            //秒杀活动和小店价不校验成本价
//            if (!ActivityEnum.FLASH_SALE.getActivity().equals(item.getActivity().getActivityType()) && !isPartnerPrice) {
//                // 不可以低于成本价
//                if (item.getFinalPrice().compareTo(item.getSku().getCostPrice()) == -1) {
//                    throw new ResultCodeException(ResultCode.LOWER_THAN_COST_PRICE);
//                }
//            }
        }
    }

    private void checkMemberPrice(List<OrderSkuItemVO> orderList) throws ResultCodeException {
        for (OrderSkuItemVO item : orderList) {
            // 计算价格
            item.setFinalPrice(getOrderSkuPrice(item));

//            //如果是合伙人商品 会员打6折
//            if (SpuTypeEnum.PARTNER.getType().equals(item.getSku().getType()) || SpuTypeEnum.ORDINARY.getType().equals(item.getSku().getType())) {
//                BigDecimal six = item.getSku().getPrice().multiply(new BigDecimal(0.6)).setScale(2, BigDecimal.ROUND_HALF_DOWN);
//                if (item.getFinalPrice().compareTo(six) > 0) {
//                    item.setFinalPrice(six);
//                }
//            }

            // 更改不打折
            if (SpuTypeEnum.PARTNER.getType().equals(item.getSku().getType()) || SpuTypeEnum.ORDINARY.getType().equals(item.getSku().getType())) {
                BigDecimal six = item.getSku().getPrice().multiply(new BigDecimal(1)).setScale(2, BigDecimal.ROUND_HALF_DOWN);
                if (item.getFinalPrice().compareTo(six) > 0) {
                    item.setFinalPrice(six);
                }
            }

//            if (!ActivityEnum.FLASH_SALE.getActivity().equals(item.getActivity().getActivityType()) && !isMemberPrice) {
//                // 不可以低于成本价
//                if (item.getFinalPrice().compareTo(item.getSku().getCostPrice()) == -1) {
//                    throw new ResultCodeException(ResultCode.LOWER_THAN_COST_PRICE);
//                }
//            }
        }
    }


    /**
     * 校验套餐的合法性
     *
     * @param orderList
     * @return
     */
    private void checkPackage(List<OrderSkuItemVO> orderList, Long userId) throws ResultCodeException {
        ActivityDTO activity = orderList.get(0).getActivity();
        if (activity != null && ActivityEnum.PACKAGES.getActivity().equals(activity.getActivityType())) {
            // 1. 判断套餐活动是否有效
            Packages packages = packagesMapper.selectByPrimaryKey(activity.getActivityId());
            if (packages == null || DeletedEnum.DELETED.getStatus().equals(packages.getDeleted()) || ToggleEnum.OFF.getStatus().equals(packages.getStatus()) || System.currentTimeMillis() < packages.getStartTime().getTime() || System.currentTimeMillis() > packages.getEndTime().getTime()) {
                throw new ResultCodeException(ResultCode.PACKAGES_INVALID);
            } else {
                // 2. 判断是否超过了套餐的限购数量
                Long count = orderSkuMapper.countPackage(userId, ActivityEnum.PACKAGES.getActivity(), activity.getActivityId());
                if (count > packages.getLimitCount() && !packages.getLimitCount().equals(0)) {
                    throw new ResultCodeException(ResultCode.OVER_ACTIVITY_STOCK_LIMIT);
                } else {
                    // 3. 判断是否存在超出套餐内的商品和数量
                    HashMap<Long, PackageSku> packageSkuHashMap = new HashMap<>();
                    List<PackageSku> packageSkuList = packageSkuMapper.findAllByActivityId(activity.getActivityId());
                    packageSkuList.stream().forEach((item) -> packageSkuHashMap.put(item.getSkuId(), item));
                    for (OrderSkuItemVO item : orderList) {
                        if (!packageSkuHashMap.containsKey(item.getSku().getId()) || !packageSkuHashMap.get(item.getSku().getId()).getCount().equals(item.getCount())) {
                            throw new ResultCodeException(ResultCode.PACKAGES_ERROR);
                        }
                    }
                }
            }
        }
    }

    /**
     * 校验预约的合法性
     *
     * @param orderList
     * @return
     */
    private void checkAppointment(List<OrderSkuItemVO> orderList, Long userId) throws ResultCodeException {
        OrderSkuItemVO vo = orderList.get(0);

        if (vo.getActivity() != null && vo.getActivity().getActivityType() != null && (ActivityEnum.BARGAIN.getActivity().equals(vo.getActivity().getActivityType()) || ActivityEnum.FLASH_SALE.getActivity().equals(vo.getActivity().getActivityType()))) {
            return;
        }

        if (vo.getAppointmentTime() == null) {
            throw new ResultCodeException(ResultCode.SETTING_APPOINTMENT);
        }

        AppointmentSetting appointmentSetting = appointmentSettingMapper.findOneBySpuId(vo.getSku().getSpuId());

        if (appointmentSetting == null) {
            throw new ResultCodeException(ResultCode.NOT_HAVE_APPOINTMENT);
        }

        List<Integer> days = JSON.parseArray(appointmentSetting.getDay(), Integer.class);

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(vo.getAppointmentTime());

        if (!days.contains(Integer.valueOf(calendar.get(Calendar.DAY_OF_WEEK)) - 1) || ToggleEnum.OFF.getStatus().equals(appointmentSetting.getStatus())) {
            throw new ResultCodeException(ResultCode.NOT_IN_APPOINTMENT_TIME);
        }

        List<HourDTO> hours = JSON.parseArray(appointmentSetting.getHour(), HourDTO.class);

        boolean passHour = false;
        Integer hour = calendar.get(Calendar.HOUR_OF_DAY);
        for (HourDTO item : hours) {
            if (item.getH().equals(hour)) {
                Long count = orderSkuMapper.countByAppointmentTime(vo.getAppointmentTime());
                if (item.getC() > count) {
                    passHour = true;
                }
            }
        }

        if (!passHour) {
            throw new ResultCodeException(ResultCode.NOT_IN_APPOINTMENT_TIME);
        }
    }

    /**
     * 校验优惠券，计算优惠金额，如果正常，则创建优惠记录并返回优惠金额
     *
     * @param orderSkuList
     * @param couponId
     * @param userId
     * @param sumPayAmount
     * @return
     * @throws ResultCodeException
     */
    private Coupon checkCoupon(List<OrderSku> orderSkuList, Long couponId, Long userId, BigDecimal sumPayAmount) throws ResultCodeException {
        if (couponId != null) {
            UserCoupon userCoupon = userCouponMapper.findOneByUserIdAndCouponId(userId, couponId);
            // 未使用的优惠券，并且属于他的
            if (UseEnum.NOT_USE.getStatus().equals(userCoupon.getStatus())) {
                Coupon coupon = couponMapper.selectByPrimaryKey(userCoupon.getCouponId());
                // 有效的优惠券
                if (ToggleEnum.ON.getStatus().equals(coupon.getStatus()) && DeletedEnum.DEFAULT.getStatus().equals((coupon.getDeleted())) && System.currentTimeMillis() > coupon.getUseStartTime().getTime() && System.currentTimeMillis() < coupon.getUseEndTime().getTime()) {
                    if (CouponTypeEnum.ALL.getType().equals(coupon.getType())) {
                        if (coupon.getPlatformType().equals(PlatformTypeEnum.PLATFORM.getType())) {
                            // 如果是全场通用
                            if (sumPayAmount.compareTo(coupon.getMinAmount()) >= 0) {
                                return coupon;
                            }
                        } else {
                            if (orderSkuList.get(0).getTenantId().equals(coupon.getTenantId())) {
                                // 如果是全场通用
                                if (sumPayAmount.compareTo(coupon.getMinAmount()) >= 0) {
                                    return coupon;
                                }
                            }
                        }
                    } else {
                        // 如果是指定SPU使用
                        // 计算每个SPU的总金额
                        HashMap<Long, BigDecimal> spuAmountMap = new HashMap<>();
                        orderSkuList.stream().forEach(item -> {
                            if (spuAmountMap.containsKey(item.getSpuId())) {
                                spuAmountMap.put(item.getSpuId(), spuAmountMap.get(item.getSpuId()).add(item.getPayAmount()));
                            } else {
                                spuAmountMap.put(item.getSpuId(), item.getPayAmount());
                            }
                        });
                        if (spuAmountMap.containsKey(coupon.getSpuId()) && spuAmountMap.get(coupon.getSpuId()).compareTo(coupon.getMinAmount()) >= 0) {
                            return coupon;
                        }
                    }
                }
            }
        }
        return null;
    }

    private BigDecimal getOrderSkuPrice(OrderSkuItemVO item) {
        return item.getActivity().getActivityType() == null ? item.getSku().getPrice() : item.getActivity().getPrice();
    }

    /**
     * 校验订单是否存在不配送区域并获得总计的运费
     *
     * @param skuList
     * @param userAddress
     * @return
     * @throws ResultCodeException
     */
    private BigDecimal checkNotDeliveryAndGetTotalFreight(List<OrderSkuItemVO> skuList, UserAddress userAddress) throws ResultCodeException {
        // 计算首重最贵的商品的全部运费，其他商品全部按续重（件）计算
        // 1、判断地址是否已经被删除
        if (userAddress == null) {
            throw new ResultCodeException(ResultCode.USER_ADDRESS_NOT_EXISTS);
        }

        // 1、获取运费中单价最贵的项
        Long province = userAddress.getProvince();
        String provinceStr = province.toString();
        FreightDTO maxFreight = new FreightDTO(BigDecimal.ZERO, BigDecimal.ZERO);
        OrderSkuItemVO maxSku = skuList.get(0);
        for (OrderSkuItemVO item : skuList) {
            // 如果存在不配送区域
            if (item.getFreight().getNotDelivery().indexOf(provinceStr) > -1) {
                throw new ResultCodeException(ResultCode.ORDER_SKU_NOT_DELIVERY);
            }
            // 如果包邮，则跳过
            if (item.getFreight().getCodes().indexOf(provinceStr) == -1) {
                // 是否是特殊运费
                Optional<FreightList> freightList = Optional.ofNullable(null);
                if (item.getFreightLists() != null && item.getFreightLists().size() > 0) {
                    freightList = item.getFreightLists().parallelStream().filter(s -> s.getProvince().equals(province)).findFirst();
                }
                if (freightList.isPresent()) {
                    if (freightList.get().getFirstWeight().compareTo(maxFreight.getFirstWeight()) == 1) {
                        maxSku = item;
                        maxFreight.setFirstWeight(freightList.get().getFirstWeight());
                        maxFreight.setAdditionalWeight(freightList.get().getAdditionalWeight());
                    }
                } else if (item.getFreight().getFirstWeight().compareTo(maxFreight.getFirstWeight()) == 1) {
                    maxSku = item;
                    maxFreight.setFirstWeight(item.getFreight().getFirstWeight());
                    maxFreight.setAdditionalWeight(item.getFreight().getAdditionalWeight());
                }
            }
        }

        // 判断是否全部包邮
        if (maxFreight.getFirstWeight().compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }

        // 计算最贵的
        BigDecimal amount = BigDecimal.ZERO;
        if (FreightTypeEnum.WEIGHT.getType().equals(maxSku.getFreight().getType())) {
            // 如果是计重
            BigDecimal weight = getSkuWeight(maxSku);
            amount = maxFreight.getFirstWeight().add((weight.compareTo(BigDecimal.ONE) == 1 ? weight.subtract(BigDecimal.ONE).multiply(maxFreight.getAdditionalWeight()) : BigDecimal.ZERO));
        } else {
            // 如果是计件
            amount = maxFreight.getFirstWeight().add(maxSku.getCount() > 1 ? maxFreight.getAdditionalWeight().multiply(new BigDecimal(maxSku.getCount() - 1)) : BigDecimal.ZERO);
        }

        // 计算其他费用
        for (OrderSkuItemVO item : skuList) {
            if (!item.getSku().getId().equals(maxSku.getSku().getId())) {
                // 先判断是否有特殊运费
                Optional<FreightList> freightList = Optional.ofNullable(null);
                if (item.getFreightLists() != null && item.getFreightLists().size() > 0) {
                    freightList = item.getFreightLists().parallelStream().filter(s -> s.getProvince().equals(province)).findFirst();
                }
                FreightDTO freightDTO = null;
                if (freightList.isPresent()) {
                    freightDTO = new FreightDTO(freightList.get().getFirstWeight(), freightList.get().getAdditionalWeight());
                } else {
                    freightDTO = new FreightDTO(item.getFreight().getFirstWeight(), item.getFreight().getAdditionalWeight());
                }
                if (FreightTypeEnum.WEIGHT.getType().equals(item.getFreight().getType())) {
                    // 如果是计重
                    BigDecimal weight = getSkuWeight(item);
                    amount = amount.add(weight.multiply(freightDTO.getAdditionalWeight()));
                } else {
                    // 如果是计件
                    amount = amount.add(freightDTO.getAdditionalWeight().multiply(new BigDecimal(item.getCount())));
                }
            }
        }
        return amount;
    }

    private BigDecimal getSkuWeight(OrderSkuItemVO item) {
        // 计算体积重量
        // 长cm×宽cm×高cm/6000
        SkuItemVO sku = item.getSku();
        BigDecimal volumeWeight = new BigDecimal(sku.getLength() * sku.getWidth() * sku.getHeight() * item.getCount()).divide(new BigDecimal("6000000"), 2, BigDecimal.ROUND_UP).setScale(0, BigDecimal.ROUND_UP);
        BigDecimal weight = sku.getWeight().multiply(new BigDecimal(item.getCount())).setScale(0, BigDecimal.ROUND_UP);
        return volumeWeight.compareTo(weight) == 1 ? volumeWeight : weight;
    }


    /**
     * 创建微信支付订单
     *
     * @param user
     * @param req
     * @param httpServletRequest
     * @return
     */
    @Override
    public ResultData<ReturnPayInfoVO> createWechatPayOrder(User user, OrderReq req, HttpServletRequest httpServletRequest) {
        Lock lock = LockCenter.getLock(Orders.class);
        try {
            lock.lock();
            if (UserStatusEnum.BAN.getStatus().equals(user.getStatus())) {
                throw new ResultCodeException(ResultCode.USER_BAN);
            }

            boolean isSelf = OrderTypeEnum.ONLINE_SELF.getType().equals(req.getOrderType());

            Date now = new Date();
            // 获取确认订单信息
            List<OrderSkuItemVO> orderList = getConfirmOrderSkuInfo(req.getOrderItemDTOList(), user.getId()).getValue();

            // 抢购的商品订单里，不可以有两个或以上的商品
            if (OrderKindEnum.COMMISSION.getKind().equals(orderList.get(0).getSku().getType()) && orderList.size() > 1) {
                throw new ResultCodeException(ResultCode.RUSH_BUY_ONLY_SINGLE);
            }

            Identity identity = identityMapper.findOneByUserId(user.getId());

            //校验新人专区商品
            checkNewZoneSpu(identity, orderList);

            //安全密码校验
            checkSecurityPassword(req.getSecurityPassword(), user, req.getPayType());

            // 校验商品状态
            checkStatus(orderList);

            // 校验库存和购买数量合法性
            checkStock(orderList, user, identity);

            // 校验价格合法性并计算最终价格


            // 默认抢购免单  如果是null 就按照小店商品价格进行结算
            if (req.getRushType() == null) {
                req.setRushType(RushTypeEnum.RUSH.getType());
            }
            Boolean isPartner = identity != null && IdentityTypeEnum.PARTNER.getType().equals(identity.getType()) && identity.getPartnerExpireTime() != null && identity.getPartnerExpireTime().after(new Date());
            Boolean isMember = identity != null && MemberStateEnum.SUPER.getType().equals(identity.getMemberState()) && identity.getMemberExpireTime() != null && identity.getMemberExpireTime().after(new Date());


            if (RushTypeEnum.RUSH.getType().equals(req.getRushType())) {
                //抢购免单 或 不是抢购商品
                if (isPartner) {
                    checkPartnerPrice(orderList);
                } else if (isMember) {
                    checkMemberPrice(orderList);
                } else {
                    checkPrice(orderList);
                }
            } else {
                if (isMember) {
                    checkPriceForRushBuy(orderList);
                } else {
                    checkPrice(orderList);
                }
            }

            // 校验套餐的合法性
            checkPackage(orderList, user.getId());

            // 检查免单合法性
            checkFree(orderList, user.getId());

            // 商店商品(所有的自提核销都是商店商品)
            Long shopId = orderList.get(0).getSku().getTenantId();
            if (isSelf) {
                checkAppointment(orderList, user.getId());
            }

            // 校验嗨币购买，不可以购买免单商品
            if (PayTypeEnum.VIP_CARD.getType().equals(req.getPayType())) {
                for (OrderSkuItemVO item : orderList) {
                    if (SpuTypeEnum.NORMAL.getType().equals(item.getSku().getType()) || SpuTypeEnum.SHOP.getType().equals(item.getSku().getType())) {
                        throw new ResultCodeException(ResultCode.CARD_POINT_CAN_NOT_BUY_IDENTITY);
                    }
                }
            }

            // 校验订单是否存在不配送区域并获得总计的运费
            UserAddress userAddress = null;
            BigDecimal totalFreight = BigDecimal.ZERO;


            if (req.getUserAddressId() != null) {
                userAddress = userAddressMapper.selectByPrimaryKey(req.getUserAddressId());
            }

            if (!isSelf) {
                totalFreight = checkNotDeliveryAndGetTotalFreight(orderList, userAddress);
            }

            SecondRelationship secondRelationship = secondRelationshipMapper.findOneBySubordinateId(user.getId());


            // 创建订单商品明细
            List<OrderSku> orderSkuList = new ArrayList<>();
            for (OrderSkuItemVO item : orderList) {
                OrderSku orderSku = OrderSku.builder()
                        .discountPrice(item.getSku().getDiscountPrice())
                        .share(item.isShare())
                        .miniCommissionScaleRebate(item.getMiniCommissionScaleRebate())
                        .miniHiCoinScaleRebate(item.getMiniHiCoinScaleRebate())
                        .beneficiaryUserId(item.getBeneficiaryUserId())
                        .shareActivityId(item.getShareActivityId())
                        .userId(user.getId())
                        .spuId(item.getSku().getSpuId())
                        .skuId(item.getSku().getId())
                        .activityId(item.getActivity().getActivityId())
                        .activityType(item.getActivity().getActivityType())
                        .count(item.getCount())
                        .price(item.getFinalPrice())
                        .defaultPrice(item.getSku().getPrice())
                        .payAmount(item.getFinalPrice().multiply(new BigDecimal(item.getCount())).subtract(item.getDiscountPrice()))
                        .productName(item.getSku().getName())
                        .status(OrdersStatusEnum.UNPAY.getStatus())
                        .createdAt(now)
                        .updatedAt(now)
                        .orderType(req.getOrderType())
                        .verifyStatus(VerifyStatusEnum.NOT_VERIFY.getStatus())
                        .shopId(shopId)
                        .appointmentTime(item.getAppointmentTime())
                        .inviteUserId(secondRelationship == null ? null : secondRelationship.getSuperiorId())
                        .tenantId(shopId)
                        // 商家金额
                        .tenantAmount(item.getSku().getCostPrice().multiply(new BigDecimal(item.getCount())))
                        .orderKind(item.getSku().getType())
                        .rushBuyStatus(OrderKindEnum.COMMISSION.getKind().equals(item.getSku().getType()) ? RushBuyStatusEnum.PENDING.getStatus() : RushBuyStatusEnum.SUCCESS.getStatus())
                        .rushType(req.getRushType())
                        .build();
                orderSkuList.add(orderSku);
            }

            // 计算需要支付的商品总价，不包含运费
            BigDecimal sumPayAmount = orderSkuList.stream().map(OrderSku::getPayAmount).reduce(BigDecimal.ZERO, BigDecimal::add);

            // 校验优惠券，计算优惠金额，如果正常，则创建优惠记录并返回优惠金额
            Coupon coupon = checkCoupon(orderSkuList, req.getCouponId(), user.getId(), sumPayAmount);

            // 检验积分
            BigDecimal coinAmount = BigDecimal.ZERO;
            // 校验并创建积分使用
            if (req.getCoinSettingId() != null) {
                // 只需要是否符合此积分使用规则，以及积分余额大于0
                CoinSetting coinSetting = coinSettingMapper.selectByPrimaryKey(req.getCoinSettingId());
                if (user.getCoin().compareTo(BigDecimal.ZERO) > 0 && coinSetting.getMinAmount().compareTo(sumPayAmount) <= 0) {
                    coinAmount = user.getCoin().compareTo(coinSetting.getCoinAmount()) > 0 ? coinSetting.getCoinAmount() : user.getCoin();
                }
            }

            // 计算付款总金额
            BigDecimal totalPayAmount = sumPayAmount.add(totalFreight);

            // 计算商户应得结算金额总和
            BigDecimal totalTenantAmount = orderSkuList.stream().map(item -> item.getTenantAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
            totalTenantAmount = totalTenantAmount.add(totalFreight);

            // 扣除积分
            if (coinAmount.compareTo(BigDecimal.ZERO) > 0) {
                totalPayAmount = totalPayAmount.subtract(coinAmount.divide(new BigDecimal(100)));
            }
            // 扣除优惠券
            if (coupon != null) {
                totalPayAmount = totalPayAmount.subtract(coupon.getDiscountAmount());

                if (coupon.getTenantId().equals(shopId)) {
                    Map<Long, Spu> spuMap = daoService.getSpuMap(orderSkuList.stream().map(OrderSku::getSpuId).collect(Collectors.toList()));
                    BigDecimal anchorCommissionSum = BigDecimal.ZERO;
                    for (OrderSku item : orderSkuList) {
                        anchorCommissionSum = anchorCommissionSum.add(item.getPayAmount().multiply(spuMap.get(item.getSpuId()).getAnchorProportion()).setScale(2, BigDecimal.ROUND_HALF_DOWN));
                    }
                    // 商家发的优惠券，由商家自己承担；平台发的优惠券，由平台承担；
                    totalTenantAmount = totalTenantAmount.subtract(coupon.getDiscountAmount());
                    if (totalTenantAmount.compareTo(BigDecimal.ZERO) < 0 || totalTenantAmount.compareTo(anchorCommissionSum) <= 0) {
                        throw new ResultCodeException(ResultCode.COUPON_NOT_VALID);
                    }
                }
            }

            // 砍价优惠
            BigDecimal bargainDiscount = BigDecimal.ZERO;
            if (req.getBargainRecordId() != null) {
                BargainRecord bargainRecord = bargainRecordMapper.selectByPrimaryKey(req.getBargainRecordId());
                if (ToggleEnum.OFF.getStatus().equals(bargainRecord.getStatus()) && bargainRecord.getUserId().equals(user.getId())) {
                    // 检查对应的SKU数量是否达标
                    for (OrderSku orderSku : orderSkuList) {
                        if (orderSku.getSkuId().equals(bargainRecord.getSkuId())) {
                            if (orderSku.getCount() >= bargainRecord.getCount()) {
                                bargainDiscount = bargainRecord.getBargainAmount();
                            }
                        }
                    }
                    if (bargainDiscount.compareTo(BigDecimal.ZERO) > 0) {
                        totalPayAmount = totalPayAmount.subtract(bargainDiscount);
                    }
                }
            }

            // 计算商品总额
            BigDecimal totalProductAmount = orderSkuList.stream().map(item -> item.getDefaultPrice().multiply(new BigDecimal(item.getCount()))).reduce(BigDecimal.ZERO, BigDecimal::add);


            if (totalPayAmount.compareTo(MAX_AMOUNT) > 0 || totalProductAmount.compareTo(MAX_AMOUNT) > 0 || totalTenantAmount.compareTo(MAX_AMOUNT) > 0) {
                ResultData<ReturnPayInfoVO> vo = new ResultData<>();
                vo.setResultCode(ResultCode.OUT_OF_AMOUNT_RANGE);
                return vo;
            }

            // 创建订单
            Orders orders = Orders.builder().userId(user.getId()).tradeNo(Long.toString(uidGenerator.getUID())).payType(req.getPayType()).status(OrdersStatusEnum.UNPAY.getStatus()).totalFreight(totalFreight).totalRefundAmount(BigDecimal.ZERO).totalPayAmount(totalPayAmount).totalProductAmount(totalProductAmount).totalTenantAmount(totalTenantAmount).logisticsStatus(LogisticsStatusEnum.UNDO.getStatus()).userMessage(req.getUserMessage()).hidden(HiddenEnum.VISIBLE.getStatus()).createdAt(now).updatedAt(now).orderType(req.getOrderType()).shopId(shopId).tenantId(shopId).freezeStatus(FreezeStatusEnum.NO_FREEZE.getStatus()).orderKind(getOrdersKind(orderList, req.getPayType())).rushBuyStatus(OrderKindEnum.COMMISSION.getKind().equals(getOrdersKind(orderList, req.getPayType())) ? RushBuyStatusEnum.PENDING.getStatus() : RushBuyStatusEnum.SUCCESS.getStatus()).rushType(req.getRushType()).build();
            ordersMapper.insert(orders);

            //创建60分钟定时任务
            quartzService.createWaitPayJob(orders);

            // 创建积分-订单优惠记录
            if (coinAmount.compareTo(BigDecimal.ZERO) > 0) {
                orderDiscountMapper.insert(OrderDiscount.builder().userId(user.getId()).orderId(orders.getId()).relateId(req.getCoinSettingId()).discountAmount(coinAmount.divide(new BigDecimal(100))).type(PromotionEnum.COIN_USE.getPromotion()).level(OrderDiscountLevelEnum.ORDER_LEVEL.getType()).status(UseEnum.NOT_USE.getStatus()).createdAt(now).updatedAt(now).build());
            }

            // 创建优惠券-订单优惠记录
            if (coupon != null) {
                orderDiscountMapper.insert(OrderDiscount.builder().userId(user.getId()).orderId(orders.getId()).spuId(coupon.getSpuId()).relateId(coupon.getId()).discountAmount(coupon.getDiscountAmount()).type(PromotionEnum.COUPON.getPromotion()).level(coupon.getType().equals(CouponTypeEnum.ALL.getType()) ? OrderDiscountLevelEnum.ORDER_LEVEL.getType() : OrderDiscountLevelEnum.SPU_LEVEL.getType()).status(UseEnum.NOT_USE.getStatus()).createdAt(now).updatedAt(now).build());
            }

            // 创建砍价优惠记录
            if (bargainDiscount.compareTo(BigDecimal.ZERO) > 0) {
                orderDiscountMapper.insert(OrderDiscount.builder().userId(user.getId()).orderId(orders.getId()).relateId(req.getBargainRecordId()).discountAmount(bargainDiscount).type(PromotionEnum.BARGAIN.getPromotion()).level(OrderDiscountLevelEnum.ORDER_LEVEL.getType()).status(UseEnum.NOT_USE.getStatus()).createdAt(now).updatedAt(now).build());
            }

            // 将订单id写入到商品明细
            orderSkuList.stream().forEach(item -> item.setOrderId(orders.getId()));
            // 批量创建订单商品明细
            orderSkuMapper.batchInsert(orderSkuList);

            for (OrderSku order : orderSkuList) {
                // 是否为分享赚商品  TODO true是  false否
                if (!order.isShare()) {
                    continue;
                }
                // 查找分享赚是否存在
                ShareActivity shareActivity = shareActivityMapper.getByShareActivityId(order.getShareActivityId());
                if (shareActivity == null) {
                    continue;
                }
                // 计算佣金金额
                ShareActivitySpu spu = shareActivitySpuMapper.getBySkuIdAndActivityId(shareActivity.getId(), order.getSkuId());
                if (spu == null) {
                    continue;
                }
                // 总支付的金额
                BigDecimal payAmount = order.getPayAmount();
                // 支付商家的金额
                BigDecimal tenantAmount = order.getTenantAmount();
                if (spu.getType()) {
                    // 佣金
                    order.setCommissionScaleRebate(spu.getCommissionScale());
                    // 嗨币
                    order.setHiCoinScaleRebate(spu.getHiCoinScale());
                } else {
                    // 佣金
                    order.setCommissionScaleRebate(payAmount.multiply(spu.getCommissionScale()).setScale(2, RoundingMode.HALF_DOWN));
                    // 嗨币
                    order.setHiCoinScaleRebate(payAmount.multiply(spu.getHiCoinScale()).setScale(2, RoundingMode.HALF_DOWN));
                }
                if (order.getMiniCommissionScaleRebate().compareTo(order.getCommissionScaleRebate()) > 0
                        || order.getMiniHiCoinScaleRebate().compareTo(order.getHiCoinScaleRebate()) > 0) {
                    try {
                        throw new ResultCodeException(ResultCode.SHARE_PRICE_UNUSUAL);
                    } catch (ResultCodeException e) {
                    }
                }
                // 扣除 佣金 以及 嗨币 实际给到商家的钱
                order.setTenantAmount(tenantAmount.subtract(order.getCommissionScaleRebate().add(order.getHiCoinScaleRebate())));
                order.setShareActivitySpuId(spu.getId());
                orderSkuMapper.updateByPrimaryKeySelective(order);
            }

            // 备份用户订单收货地址
            if (userAddress != null) {
                OrderAddress orderAddress = OrderAddress.builder().build();
                BeanUtils.copyProperties(userAddress, orderAddress);
                orderAddress.setId(null);
                orderAddress.setOrderId(orders.getId());
                orderAddress.setUserAddressId(req.getUserAddressId());
                orderAddressMapper.insert(orderAddress);
            }

            //快递助手创建订单 mallUserId存在才能生成订单
//            kuaidizsService.createTrade(orders);

            // 支付金额不可以小于等于0
            if (totalPayAmount.compareTo(BigDecimal.ZERO) < 0) {
                throw new ResultCodeException(ResultCode.CAN_NOT_PAY_UNDER_ZERO);
            }

            ReturnPayInfoVO infoVO = new ReturnPayInfoVO();
            // 微信支付
            if (PayTypeEnum.WECHAT.getType().equals(req.getPayType()) || PayTypeEnum.APP_WECHAT.getType().equals(req.getPayType())) {
                if (orders.getTotalPayAmount().compareTo(BigDecimal.ZERO) > 0) {
                    // 创建微信支付
                    final WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = WxPayUnifiedOrderRequest.newBuilder().openid(PayTypeEnum.WECHAT.getType().equals(req.getPayType()) ? user.getOpenid() : null).outTradeNo(orders.getTradeNo())
                            //订单金额, 单位：分
                            .totalFee(orders.getTotalPayAmount().multiply(new BigDecimal(100)).intValue()).body(StringHelper.subPayBodyString(orderList.get(0).getSku().getName()) + (orderList.size() > 1 ? "等" + orderList.size() + "件商品" : "")).spbillCreateIp(IpUtil.getIpAddr(httpServletRequest)).notifyUrl(domainUrl + "/api/order/wechatOrderNotify").build();

                    if (PayTypeEnum.WECHAT.getType().equals(req.getPayType())) {
                        wxPayUnifiedOrderRequest.setAppid(miniAppId);
                        wxPayUnifiedOrderRequest.setTradeType("JSAPI");
                    } else {
                        wxPayUnifiedOrderRequest.setAppid(appAppId);
                        wxPayUnifiedOrderRequest.setTradeType("APP");
                    }

                    infoVO = commonService.getReturnPayInfoVO(wxPayUnifiedOrderRequest);
                }
            }
            // 嗨币支付
            if (PayTypeEnum.VIP_CARD.getType().equals(req.getPayType())) {

                // 判断余额是否足够
                if (orders.getTotalPayAmount().compareTo(user.getCardPoint()) > 0) {
                    throw new ResultCodeException(ResultCode.CARD_POINT_NOT_ENOUGH);
                } else {
                    // 余额充足，扣除余额
                    BigDecimal afterPayCardPoint = user.getCardPoint().subtract(orders.getTotalPayAmount());
                    userMapper.updateCardPointById(afterPayCardPoint, user.getId());

                    // 创建消费记录
                    cardFlowMapper.insert(CardFlow.builder().userId(user.getId()).amount(orders.getTotalPayAmount()).tradeType(CardTradeTypeEnum.PAY.getTradeType()).type(CardTradeTypeEnum.PAY.getType()).cardPoint(afterPayCardPoint).relateId(orders.getId()).remark(StringHelper.subPayBodyString(orderList.get(0).getSku().getName()) + (orderList.size() > 1 ? "等" + orderList.size() + "件商品" : "")).createdAt(new Date()).build());

                    // 完成支付
                    completePay(orders.getTradeNo());
                    //todo 发送嗨币余额短信
                    smsService.sendShopOrderSms(subShopOrderPayBodyString("剩余嗨币:" + afterPayCardPoint), user.getUsername());
                }
            }

            // 兑换卡
            if (PayTypeEnum.EXCHANGE_CARD.getType().equals(req.getPayType())) {
                // 判断兑换的数量是否正确
                if (orderSkuList.size() == 1 && orderSkuList.get(0).getCount() == 1L) {
                    UserVoucher userVoucher = userVoucherMapper.selectByPrimaryKey(req.getUserVoucherId());
                    if (userVoucher != null && userVoucher.getUserId().equals(user.getId()) && VoucherStatusEnum.AVAILABLE.getStatus().equals(userVoucher.getStatus())) {
                        userVoucher.setUseOrderSkuId(orderSkuList.get(0).getId());
                        userVoucher.setStatus(VoucherStatusEnum.USED.getStatus());
                        userVoucher.setUseTime(new Date());
                        userVoucherMapper.updateByPrimaryKeySelective(userVoucher);

                        // 完成支付
                        completePay(orders.getTradeNo());

                        // 对原先的秒杀卡或砍价卡订单，设置为已完成
                        if (userVoucher.getFromOrderSkuId() != null) {
                            OrderSku cardOrderSku = orderSkuMapper.selectByPrimaryKey(userVoucher.getFromOrderSkuId());
                            ordersMapper.updateStatusAndCompleteTimeById(OrdersStatusEnum.DONE.getStatus(), new Date(), cardOrderSku.getOrderId());
                            orderSkuMapper.updateStatusByOrderId(OrdersStatusEnum.DONE.getStatus(), cardOrderSku.getOrderId());
                        }
                    } else {
                        throw new ResultCodeException(ResultCode.EXCHANGE_CARD_INVALID);
                    }
                } else {
                    throw new ResultCodeException(ResultCode.EXCHANGE_CARD_ONLY_PAY_ONE);
                }
            }

            // 删除此用户购物车中对应的商品(无论是否支付成功)
            List<Long> skuIds = orderSkuList.stream().map(OrderSku::getSkuId).collect(Collectors.toList());
            shoppingCartMapper.deleteByUserIdAndSkuIds(orders.getUserId(), skuIds);

            // 删除用户未支付的订单
            if (req.getUnpaidOrderId() != null) {
                Orders unpaidOrder = ordersMapper.selectByPrimaryKey(req.getUnpaidOrderId());
                if (unpaidOrder != null && OrdersStatusEnum.UNPAY.getStatus().equals(unpaidOrder.getStatus())) {
                    ordersMapper.deleteByIdAndStatus(req.getUnpaidOrderId(), OrdersStatusEnum.UNPAY.getStatus());
                    orderSkuMapper.deleteByOrderIdAndStatus(req.getUnpaidOrderId(), OrdersStatusEnum.UNPAY.getStatus());
                    orderAddressMapper.deleteByOrderId(req.getUnpaidOrderId());
                }
            }
            // TODO 测试环境忽略微信订单回调更改订单状态
            if ("https://hipo.lanchetech.com".equals(domainUrl) && PayTypeEnum.WECHAT.getType().equals(req.getPayType())) {
                completePay(orders.getTradeNo());
            } else {
                // 如果是0元，则直接完成订单
                if (orders.getTotalPayAmount().compareTo(BigDecimal.ZERO) == 0) {
                    completePay(orders.getTradeNo());
                }
            }

            infoVO.setOrderId(orders.getId());

            orderSkuList.stream().forEach(item -> {
                deleteRedisByKey("SkuList:" + item.getSpuId() + ":*");
            });


            return new ResultData<>(infoVO);
        } catch (ResultCodeException e) {
            e.printStackTrace();
            ResultData<ReturnPayInfoVO> resultData = new ResultData<>();
            resultData.setResultCode(e.getResultCode());
            return resultData;
        } finally {
            lock.unlock();
        }
    }


    private Byte getOrdersKind(List<OrderSkuItemVO> orderList, Byte payType) {
        Byte orderKind = 0;
        if (PayTypeEnum.VIP_CARD.getType().equals(payType)) {
            orderKind = OrderKindEnum.EXCHANGE.getKind();
        }
        for (OrderSkuItemVO item : orderList) {
            orderKind = item.getSku().getType();
            if (OrderKindEnum.SHOP.getKind().equals(orderKind) || OrderKindEnum.NORMAL.getKind().equals(orderKind)) {
                break;
            }
        }
        return orderKind;
    }

    @Override
    public ResultData<Byte> getOrderStatus(Long id) {
        Orders orders = ordersMapper.selectByPrimaryKey(id);
        return new ResultData<>(orders != null ? orders.getStatus() : OrdersStatusEnum.UNPAY.getStatus());
    }

    /**
     * 订单支付成功后处理
     *
     * @param tradeNo
     */
    private void completePay(String tradeNo) {
        Orders orders = ordersMapper.findOneByTradeNo(tradeNo);

        if (OrdersStatusEnum.CLOSE.getStatus().equals(orders.getStatus())) {
            return;
        }

        //更新店铺统计数据
        List<Orders> userOrders = ordersMapper.findAllByUserIdAndShopId(orders.getUserId(), orders.getShopId());
        shopStatisticsMapper.updateCompletePay(ShopStatistics.builder().shopId(orders.getShopId()).orderAmount(orders.getTotalPayAmount()).customCount(userOrders.size() > 1 ? 0L : 1L).updatedAt(new Date()).build());

        // 更新订单状态和支付时间
        ordersMapper.updateStatusAndPayTimeByTradeNo(OrdersStatusEnum.PAID.getStatus(), new Date(), tradeNo);
        orderSkuMapper.updateStatusByOrderId(OrdersStatusEnum.PAID.getStatus(), orders.getId());

        // 更新优惠明细状态
        orderDiscountMapper.updateStatusAndUpdatedAtByOrderId(UseEnum.USED.getStatus(), new Date(), orders.getId());

        // 如果是代付，则更新代付状态
        if (PayTypeEnum.ANOTHER_APY.getType().equals(orders.getPayType())) {
            orderPayMapper.updateStatusAndUpdatedAtByTradeNo(OrderPayStatusEnum.PAID.getStatus(), new Date(), orders.getTradeNo());
        }

        // 将此订单中使用的优惠券，状态变更; 将此订单的使用的积分从个人积分余额中扣除;
        List<OrderDiscount> orderDiscountList = orderDiscountMapper.findAllByOrderId(orders.getId());
        if (!CollectionUtils.isEmpty(orderDiscountList)) {
            for (OrderDiscount item : orderDiscountList) {
                if (PromotionEnum.COUPON.getPromotion().equals(item.getType())) {
                    userCouponMapper.updateStatusAndUpdatedAtByUserIdAndCouponId(UseEnum.USED.getStatus(), new Date(), orders.getUserId(), item.getRelateId());
                }
                if (PromotionEnum.COIN_USE.getPromotion().equals(item.getType())) {
                    User user = userMapper.selectByPrimaryKey(orders.getUserId());
                    userMapper.updateCoinById(user.getCoin().subtract(item.getDiscountAmount()), user.getId());

                    // 创建积分使用记录
                    coinFlowMapper.insert(CoinFlow.builder().
                            userId(user.getId())
                            .amount(item.getDiscountAmount())
                            .tradeType(CoinFlowTradeTypeEnum.CONSUME.getTradeType())
                            .type(CoinFlowTradeTypeEnum.CONSUME.getType())
                            .coin(user.getCoin().subtract(item.getDiscountAmount()))
                            .relateId(item.getOrderId()).remark("支付订单使用积分优惠")
                            .createdAt(new Date())
                            .build());
                }
                if (PromotionEnum.BARGAIN.getPromotion().equals(item.getType())) {
                    bargainRecordMapper.updateStatusAndUpdatedAtById(UseEnum.USED.getStatus(), new Date(), item.getId());
                }
            }
        }

        User user = userMapper.selectByPrimaryKey(orders.getUserId());

        // 支付成功了，就增加sku, spu销量数量
        // 减少sku库存
        List<OrderSkuVO> orderSkuVOList = orderSkuMapper.findAllByOrderId(orders.getId());
        Map<Long, Integer> spuCountMap = new HashMap<>();
        orderSkuVOList.stream().forEach(item -> {
            spuCountMap.put(item.getSpuId(), spuCountMap.containsKey(item.getSpuId()) ? spuCountMap.get(item.getSpuId()) + item.getCount() : item.getCount());
            skuMapper.updateStockAndSalesById(item.getCount(), item.getSkuId());
            // 如果商品参加了活动，则更新活动库存
            // 限时优惠
            if (ActivityEnum.FLASH_SALE.getActivity().equals(item.getActivityType())) {
                flashSaleSkuMapper.updateStockAndSalesByActivityIdAndSkuId(item.getCount(), item.getActivityId(), item.getSkuId());
                flashSaleSpuMapper.updateSalesAndUpdatedAtByActivityIdAndSpuId(item.getCount(), new Date(), item.getActivityId(), item.getSpuId());

                // 如果是线上自提，则发放秒杀兑换卡
                if (OrderTypeEnum.ONLINE_SELF.getType().equals(item.getOrderType())) {
                    for (int i = 0; i < item.getCount(); i++) {
                        userVoucherMapper.insert(UserVoucher.builder().userId(item.getUserId()).fromOrderSkuId(item.getId()).productName(item.getProductName()).shopId(item.getShopId()).spuId(item.getSpuId()).type(VoucherTypeEnum.FLASH_SALE.getType()).status(VoucherStatusEnum.AVAILABLE.getStatus()).createdAt(new Date()).updatedAt(new Date()).build());
                    }
                }
            }

            // 砍价
            if (ActivityEnum.BARGAIN.getActivity().equals(item.getActivityType())) {
                bargainSkuMapper.updateStockAndSalesByActivityIdAndSkuId(item.getCount(), item.getActivityId(), item.getSkuId());

                // 发放秒杀兑换卡
                if (OrderTypeEnum.ONLINE_SELF.getType().equals(item.getOrderType())) {
                    for (int i = 0; i < item.getCount(); i++) {
                        userVoucherMapper.insert(UserVoucher.builder().userId(item.getUserId()).fromOrderSkuId(item.getId()).productName(item.getProductName()).shopId(item.getShopId()).spuId(item.getSpuId()).type(VoucherTypeEnum.BARGAIN.getType()).status(VoucherStatusEnum.AVAILABLE.getStatus()).createdAt(new Date()).updatedAt(new Date()).build());
                    }
                }
            }

            if (OrderTypeEnum.ONLINE_SELF.getType().equals(item.getOrderType())) {
                // 农场任务
                boolean done = commonFarmService.checkTaskDone(user, FarmTaskKindEnum.TARGET_SHOP_SPU.getKind(), item.getSpuId(), Long.valueOf(item.getCount()));
                if (!done) {
                    commonFarmService.checkTaskDone(user, FarmTaskKindEnum.ALL_SHOP_SPU.getKind(), item.getSpuId(), Long.valueOf(item.getCount()));
                }
            }
            // 是否为分享赚商品
            if (item.isShare()) {
                saveShareDetails(item);
            }
            // 是否为消费金
            if (ActivityEnum.CONSUMPTION_FUND.getActivity().equals(item.getActivityType())) {
                // 查询消费金
                CardConsumptionUserVo cardConsumptionUser = cardConsumptionUserMapper.getCardConsumptionUser(user.getId());
                if (cardConsumptionUser.getAmt().compareTo(item.getDiscountPrice()) >= 0) {

                    // 生成消费金流水记录
                    UserAmtLog userAmtLog = new UserAmtLog();
                    userAmtLog.setRemark("商品下单扣除消费金:-" + item.getDiscountPrice());
                    userAmtLog.setCreated(new Date());
                    userAmtLog.setType((byte) 2);
                    userAmtLog.setUserId(cardConsumptionUser.getUserId());
                    userAmtLog.setAmt(item.getDiscountPrice());
                    userAmtLog.setBeforeAmt(cardConsumptionUser.getAmt());
                    userAmtLog.setAfterAmt(cardConsumptionUser.getAmt().subtract(item.getDiscountPrice()));
                    userAmtLogMapper.insert(userAmtLog);

                    // 扣除消费金
                    cardConsumptionUser.setAmt(cardConsumptionUser.getAmt().subtract(item.getDiscountPrice()));
                    cardConsumptionUserMapper.updateConsumptionUser(cardConsumptionUser);
                }
            }
        });
        //新人专区商品就更新identity
        List<ZoneSpu> zoneSpuList = zoneSpuMapper.findAllBySpuIdInAndNewZone(orderSkuVOList.stream().map(OrderSkuVO::getSpuId).collect(Collectors.toList()), ToggleEnum.ON.getStatus());
        if (!CollectionUtils.isEmpty(zoneSpuList)) {
            identityMapper.updateNewZoneBuyAndUpdateAtByUserId(ToggleEnum.ON.getStatus(), new Date(), user.getId());
        }


        for (Map.Entry<Long, Integer> item : spuCountMap.entrySet()) {
            spuMapper.updateSalesById(item.getValue(), item.getKey());
            deleteRedisByKey("ProductDetail:" + item.getKey() + ":*");
        }

        // 发放积分奖励
        if (!PayTypeEnum.EXCHANGE_CARD.getType().equals(orders.getPayType())) {
            // 发放积分奖励
            issueCoinReward(orders.getUserId(), orderSkuVOList);
            // 发放嗨跑佣金      发放身份
            commissionService.prepareHipoCommission(orderSkuVOList);

            // 创建消费记录
            consumptionService.updateConsumptionAmount(ConsumptionRecord.builder().userId(orders.getUserId()).amount(orders.getTotalPayAmount()).recordType(ConsumptionRecordTypeEnum.CONSUMPTION.getRecordType()).relateId(orders.getId()).remark(StringHelper.subPayBodyString(orderSkuVOList.get(0).getProductName()) + (orderSkuVOList.size() > 1 ? "等" + orderSkuVOList.size() + "件商品" : "")).build());
        }

        // 如果是商家自提订单，则发钱给商家(兑换卡类型的，销售时就发钱，兑换时就不要重复发钱)
        // 抢购订单在抢购成功时再处理
        if (!PayTypeEnum.EXCHANGE_CARD.getType().equals(orders.getPayType()) && orders.getOrderKind() != OrderKindEnum.COMMISSION.getKind()) {
            completeShopOrder(orders, orderSkuVOList, user);
        }
        if (orders.getOrderKind().equals(OrderKindEnum.COMMISSION.getKind()) && RushTypeEnum.BUY.getType().equals(orders.getRushType())) {
            completeShopOrder(orders, orderSkuVOList, user);
        }

        TriggerKey triggerKey = TriggerKey.triggerKey("ORDER_PAY_TRIGGER" + orders.getId().toString(), "WAIT_PAY");
        JobKey jobKey = JobKey.jobKey("WAIT_PAY_JOB" + orders.getId().toString(), "WAIT_PAY");
        try {
            //关闭定时任务
            scheduler.pauseTrigger(triggerKey);
            // 移除触发器中的任务
            scheduler.unscheduleJob(triggerKey);
            // 删除任务
            scheduler.deleteJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }

        //编辑商户通知消息
        announcementService.sendOrderAnnouncement(orders);

        //修改快递助手中的订单状态
        Shop shop = shopMapper.selectByPrimaryKey(orders.getTenantId());
        updateKuaidizsStatus(KdzsOrderStatusEnum.ORDER_PAID.getStatus(), orders.getId(), shop.getMallUserId());
        // */
    }

    private void saveShareDetails(OrderSkuVO item) {
        // 查找绑定的商品
        ShareActivitySpuVo activitySpu = shareActivitySpuMapper.getOneShareActivitySpuById(item.getShareActivitySpuId());
        if (activitySpu == null) {
            return;
        }
//        ShareUserLevel shareUserLevel = shareUserLevelMapper.getRecentlyByUserId(item.getUserId());
//        if (shareUserLevel == null) {
        // 生成分享人与下单人关系记录
        shareUserLevelMapper.insert(ShareUserLevel.builder()
                .orderSkuId(item.getId())
                .higherLevelUserId(item.getBeneficiaryUserId())
                .lowerLevelUserId(item.getUserId())
                .created(new Date()).build());
//        } else {
        // 生成分享人佣金记录
        ShareDetailed commission = new ShareDetailed();
        commission.setCommissionRebate(item.getCommissionScaleRebate());
        commission.setCommissionScale(activitySpu.getCommissionScale());
        commission.setBeneficiaryUserId(item.getBeneficiaryUserId());
        extracted(item, activitySpu, commission, ShareRebateEnum.COMMISSION.getCode());
        shareDetailedMapper.insert(commission);
//        }
        // 查找分享人是否有上级
        Long higherLevelUserId = shareUserLevelMapper.getRecentlyByHigherLevelUserId(item.getBeneficiaryUserId());
        if (higherLevelUserId != null) {
            ShareDetailed hiCoin = new ShareDetailed();

            // 分享人的上级嗨币提成
            if (item.getHiCoinScaleRebate().compareTo(BigDecimal.ZERO) > 0) {
                // 生成给上级的上级嗨币记录
                hiCoin.setHiCoinRebate(item.getHiCoinScaleRebate());
                hiCoin.setHiCoinScale(activitySpu.getHiCoinScale());
                hiCoin.setBeneficiaryUserId(higherLevelUserId);
                extracted(item, activitySpu, hiCoin, ShareRebateEnum.HICOIN.getCode());
                // 放入上级的上级嗨币记录
                shareDetailedMapper.insert(hiCoin);
            }
        }
    }

    private void extracted(OrderSkuVO item,
                           ShareActivitySpuVo activitySpu,
                           ShareDetailed shareDetailed,
                           int shareRebateEnumCode) {
        shareDetailed.setCount(item.getCount());
        shareDetailed.setAmount(item.getPrice());
        shareDetailed.setShareActivityId(activitySpu.getShareActivityId());
        shareDetailed.setOrderSkuId(item.getId());
        shareDetailed.setProviderUserId(item.getUserId());
        shareDetailed.setShareActivitySpuId(item.getShareActivitySpuId());
        shareDetailed.setFreeze(false);
        shareDetailed.setCreated(new Date());
        shareDetailed.setType(shareRebateEnumCode);
        shareDetailed.setShareActivitySpuType(activitySpu.getType());
        shareDetailed.setTenantId(item.getTenantId());
    }

    /**
     * 订单支付完成，可以进行发货了
     *
     * @param orders
     * @param orderSkuVOList
     * @param user
     */
    @Override
    public void completeShopOrder(Orders orders, List<OrderSkuVO> orderSkuVOList, User user) {
        Shop shop = shopMapper.selectByPrimaryKey(orders.getShopId());
        if (shop != null && shop.getUserId() != null) {
            smsService.sendShopOrderSms(subShopOrderPayBodyString((user.getNickname().length() > 5 ? user.getNickname().substring(0, 5) : user.getNickname()) + "|" + orderSkuVOList.get(0).getProductName()), userMapper.selectByPrimaryKey(shop.getUserId()).getUsername());
        }
        if (orders.getTotalPayAmount().compareTo(BigDecimal.ZERO) > 0) {
            // 每个订单里最多只能有1个商品

            // 立即发放商品销售收入给商户
            Tenant tenant = tenantMapper.selectByPrimaryKey(shop.getId());
            tenantFlowMapper.insert(TenantFlow.builder()
                    .amount(orders.getTotalTenantAmount())
                    .tradeType(TenantTradeTypeEnum.PRODUCT.getTradeType())
                    .type(TenantTradeTypeEnum.PRODUCT.getType())
                    .point(tenant.getPoint().add(orders.getTotalTenantAmount()))
                    .relateId(orders.getId())
                    .remark(orderSkuVOList.get(0).getProductName())
                    .createdAt(new Date())
                    .tenantId(tenant.getId())
                    .build());
            tenantMapper.updatePointById(tenant.getPoint().add(orders.getTotalTenantAmount()), tenant.getId());
            financeService.createFreezeAmount(orders, orders.getTotalTenantAmount(), FreezeTypeEnum.ORDERS.getType());
        }
    }

    private void updateKuaidizsStatus(String status, Long orderId, Long mallUserId) {
        KdzsPrintTradeUpdateRequest updateRequest = new KdzsPrintTradeUpdateRequest();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        updateRequest.setModified(format.format(new Date()));
        updateRequest.setTid(orderId.toString());
        updateRequest.setStatus(status);
        updateRequest.setMallUserId(mallUserId);
        kuaidizsService.updateTrade(updateRequest);
    }


    /**
     * @param source 需要过滤的字符串
     * @return
     */
    public static String subShopOrderPayBodyString(String source) {
        if (source.length() > 20) {
            return source.substring(0, 19);
        }
        return source;
    }

    /**
     * 发放积分奖励
     *
     * @param userId
     * @param orderSkuVOList
     */
    private void issueCoinReward(Long userId, List<OrderSkuVO> orderSkuVOList) {
        // 获取所有积分奖励设置
        List<Long> spuIds = new ArrayList<>();
        Map<Long, Integer> spuCountMap = new HashMap<>();
        orderSkuVOList.stream().forEach(item -> {
            if (!spuIds.contains(item.getSpuId())) {
                spuIds.add(item.getSpuId());
                spuCountMap.put(item.getSpuId(), item.getCount());
            } else {
                spuCountMap.put(item.getSpuId(), spuCountMap.get(item.getSpuId()) + item.getCount());
            }
        });
        List<CoinReward> coinRewardList = coinRewardMapper.findAllBySpuIdsAndNow(spuIds, new Date());
        if (!CollectionUtils.isEmpty(coinRewardList)) {
            // 计算积分奖励总额
            BigDecimal coinAmount = BigDecimal.ZERO;
            for (CoinReward coinReward : coinRewardList) {
                if (spuCountMap.get(coinReward.getSpuId()) > coinReward.getCount()) {
                    coinAmount = coinAmount.add(coinReward.getCoin().multiply(new BigDecimal(coinReward.getCount())));
                } else {
                    coinAmount = coinAmount.add(coinReward.getCoin().multiply(new BigDecimal(spuCountMap.get(coinReward.getSpuId()))));
                }
            }
            if (coinAmount.compareTo(BigDecimal.ZERO) > 0) {
                // 更新用户积分余额
                User user = userMapper.selectByPrimaryKey(userId);
                userMapper.updateCoinById(user.getCoin().add(coinAmount), user.getId());
                // 创建积分奖励记录
                coinFlowMapper.insert(CoinFlow.builder().userId(user.getId()).amount(coinAmount).tradeType(CoinFlowTradeTypeEnum.REWARD.getTradeType()).type(CoinFlowTradeTypeEnum.REWARD.getType()).coin(user.getCoin().add(coinAmount)).relateId(orderSkuVOList.get(0).getOrderId()).remark("购买商品奖励收入").createdAt(new Date()).build());
            }
        }
    }

    /**
     * 发放专栏和课程权限(允许重复发)
     *
     * @param userId
     * @param orderSkuVOList
     */
    private void issueColumnCourseAuth(Long userId, List<OrderSkuVO> orderSkuVOList) {
        List<SkuColumnCourse> skuColumnCourseList = skuColumnCourseMapper.findAllBySkuIds(orderSkuVOList.stream().map(OrderSkuVO::getSkuId).collect(Collectors.toList()));

        if (!CollectionUtils.isEmpty(skuColumnCourseList)) {
            Map<Long, Long> orderSkuIdMap = new HashMap<>();
            orderSkuVOList.stream().forEach(item -> orderSkuIdMap.put(item.getSkuId(), item.getId()));
            List<ColumnCourseAuth> columnCourseAuthList = new ArrayList<>();

            skuColumnCourseList.stream().forEach(item -> {
                ColumnCourseAuth auth = new ColumnCourseAuth();
                BeanUtils.copyProperties(item, auth, "id", "createdAt");
                auth.setUserId(userId);
                auth.setOrderSkuId(orderSkuIdMap.get(item.getSkuId()));
                auth.setCreatedAt(new Date());
                columnCourseAuthList.add(auth);
            });

            columnCourseAuthMapper.batchInsert(columnCourseAuthList);
        }
    }

    /**
     * 微信支付成功回调
     *
     * @param xmlData
     * @return
     */
    @Override
    public String wechatOrderNotify(String xmlData) {
        try {
            wxPayService.getConfig().setAppId(xmlData.indexOf(miniAppId) > -1 ? miniAppId : appAppId);
            wxPayService.getConfig().setTradeType(xmlData.indexOf(miniAppId) > -1 ? "JSAPI" : "APP");
            final WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
            // 检查微信支付成功地回调是否是他人伪造
            notifyResult.checkResult(wxPayService, "MD5", true);
            log.info("订单号：{}, 商品购买微信支付成功！", notifyResult.getOutTradeNo());
            completePay(notifyResult.getOutTradeNo());
            // TODO 发送小程序模板消息通知
            return WxPayNotifyResponse.success("回调成功！");
        } catch (WxPayException e) {
            e.printStackTrace();
            log.error("微信支付失败！");
            return WxPayNotifyResponse.fail("回调有误!");
        }
    }

    @Override
    public BaseResp addToShoppingCart(User user, ShoppingCart shoppingCart) {
        if (shoppingCart.getSkuId() == null) {
            Sku sku = skuMapper.findTopOneBySpuId(shoppingCart.getSpuId());
            shoppingCart.setSkuId(sku.getId());
        }

        ShoppingCart result = shoppingCartMapper.findOneByUserIdAndSkuId(user.getId(), shoppingCart.getSkuId());

        if (result == null) {
            // 如果购物车数量超过20件，则不允许再添加商品到购物车中
            Long count = shoppingCartMapper.countByUserId(user.getId());
            if (count >= 20) {
                return new BaseResp(ResultCode.OVER_MAX_SHOPPING_CART);
            }

            Spu spu = spuMapper.selectByPrimaryKey(shoppingCart.getSpuId());

            shoppingCart.setUserId(user.getId());
            shoppingCart.setCreatedAt(new Date());
            shoppingCart.setTenantId(spu.getTenantId());
            shoppingCartMapper.insert(shoppingCart);
        } else {
            result.setCount(result.getCount() + shoppingCart.getCount());
            shoppingCartMapper.updateByPrimaryKey(result);
        }

        return new BaseResp();
    }

    @Override
    public ResultData<ShoppingCartVO> getShoppingCartSkuInfo(User user) {
        ShoppingCartVO vo = new ShoppingCartVO();

        vo.setAvailableCoupon(couponMapper.findOneTopCoupon());

        List<ShoppingCart> shoppingCartList = shoppingCartMapper.findAllByUserId(user.getId());

        if (CollectionUtils.isEmpty(shoppingCartList)) {
            return new ResultData<>(vo);
        }

        List<OrderItemDTO> orderItemDTOList = new ArrayList<>();
        shoppingCartList.forEach(item -> {
            OrderItemDTO orderItemDTO = new OrderItemDTO();
            BeanUtils.copyProperties(item, orderItemDTO);
            orderItemDTOList.add(orderItemDTO);
        });

        List<OrderSkuItemVO> list = getConfirmOrderSkuInfo(orderItemDTOList, user.getId()).getValue();
        Map<Long, Shop> map = daoService.getShopMap(shoppingCartList.stream().map(ShoppingCart::getTenantId).collect(Collectors.toList()));
        list.stream().forEach(item -> {
            item.setTenantId(item.getSku().getTenantId());
            item.setTenantNickname(map.get(item.getSku().getTenantId()).getShopName());
        });

        vo.setOrderSkuItemVOList(list);
        return new ResultData<>(vo);
    }

    @Override
    public BaseResp deleteShoppingCart(User user, Long skuId, String skuIdStr) {
        if (skuId != null) {
            shoppingCartMapper.deleteByUserIdAndSkuId(user.getId(), skuId);
        }
        if (skuIdStr != null) {
            String[] split = skuIdStr.split(",");
            List<Long> skuIds = new ArrayList<>();
            for (String s : split) {
                skuIds.add(Long.valueOf(s));
            }
            shoppingCartMapper.deleteByUserIdAndSkuIds(user.getId(), skuIds);
        }

        return new BaseResp();
    }

    /**
     * 默认的获取订单分页
     *
     * @param req
     * @return
     */
    public ResultData<BasePageResp<OrderResp>> getOrderPageDefault(PageReq req) {
        // 获取订单列表
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<OrderResp> orderList = ordersMapper.findAllFrontPage(req);
        if (CollectionUtils.isEmpty(orderList)) {
            return PageHelpUtil.buildPage(new ArrayList<>(), page);
        }

        List<Long> shopIds = new ArrayList<>();
        orderList.stream().forEach(item -> {
            if (item.getShopId() != null && !shopIds.contains(item.getShopId())) {
                shopIds.add(item.getShopId());
            }
        });

        List<Long> orderIds = orderList.stream().map(item -> item.getId()).collect(Collectors.toList());

        // 获取订单商品明细列表
        List<OrderSkuVO> orderSkuList = orderSkuMapper.findAllByOrderIds(orderIds);
        List<Long> tenantIds = new ArrayList<>();
        List<Long> skuIds = new ArrayList<>();
        orderSkuList.forEach(item -> {
            if (!skuIds.contains(item.getSkuId())) {
                skuIds.add(item.getSkuId());
            }
            if (!tenantIds.contains(item.getTenantId())) {
                tenantIds.add(item.getTenantId());
            }
        });

        // 获取商品sku信息
        Map<Long, Sku> skuMap = daoService.getSkuMap(skuIds);
        Map<Long, List<OrderSkuVO>> orderSkuMap = new HashMap<>();
        // 组装数据
        orderSkuList.stream().forEach((item) -> {
            item.setImage(skuMap.get(item.getSkuId()).getImage());
            item.setSpecNames(skuMap.get(item.getSkuId()).getSpecNames());
            item.setSpecValues(skuMap.get(item.getSkuId()).getSpecValues());
            item.setSpuType(skuMap.get(item.getSkuId()).getType());
            if (orderSkuMap.containsKey(item.getOrderId())) {
                orderSkuMap.get(item.getOrderId()).add(item);
            } else {
                List<OrderSkuVO> list = new ArrayList<>();
                list.add(item);
                orderSkuMap.put(item.getOrderId(), list);
            }
        });


        Map<Long, Shop> shopMap = shopIds.isEmpty() ? new HashMap<>() : daoService.getShopMap(shopIds);
        orderList.stream().forEach(item -> {
            item.setOrderSkuList(orderSkuMap.get(item.getId()));
            if (item.getShopId() != null) {
                item.setShopName(shopMap.get(item.getShopId()).getShopName());
                item.setShopAvatar(shopMap.get(item.getShopId()).getAvatar());
            }
            item.setTenantNickname(shopMap.get(item.getTenantId()) != null ? shopMap.get(item.getTenantId()).getShopName() : null);
        });

        if (req.getShopId() != null) {
            List<Long> userIds = orderList.stream().map(Orders::getUserId).collect(Collectors.toList());

            // 寻找这订单的上级用户
            List<UserRelationship> userRelationshipList = userRelationshipMapper.findAllBySubordinateIdIn(userIds);
            Map<Long, Long> superMap = new HashMap<>();
            if (!userRelationshipList.isEmpty()) {
                userRelationshipList.stream().forEach(item -> {
                    superMap.put(item.getSubordinateId(), item.getSuperiorId());
                    userIds.add(item.getSuperiorId());
                });
            }

            Map<Long, User> userMap = daoService.getUserMap(userIds);

            orderList.stream().forEach(item -> {
                item.setUserNickname(userMap.get(item.getUserId()).getNickname());
                item.setUserAvatar(userMap.get(item.getUserId()).getAvatar());
                if (superMap.containsKey(item.getUserId())) {
                    item.setSuperiorUserId(superMap.get(item.getUserId()));
                    item.setSuperiorNickname(userMap.get(superMap.get(item.getUserId())).getNickname());
                    item.setSuperiorAvatar(userMap.get(superMap.get(item.getUserId())).getAvatar());
                }
            });
        }

        ResultData<BasePageResp<OrderResp>> resultData = PageHelpUtil.buildPage(orderList, page);
        resultData.getValue().setExtra(ordersMapper.sumPageAmount(req));

        return resultData;
    }

    /**
     * 根据商品名称获取订单分页
     *
     * @param req
     * @return
     */
    public ResultData<BasePageResp<OrderResp>> getOrderPageByName(PageReq req) {

        // 获取订单列表
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<OrderSkuVO> orderSkuList = orderSkuMapper.findAllByProductName(req);

        if (CollectionUtils.isEmpty(orderSkuList)) {
            return PageHelpUtil.buildPage(new ArrayList<>(), page);
        }

        List<Long> orderIds = new ArrayList<>();
        List<Long> skuIds = new ArrayList<>();
        List<Long> tenantIds = new ArrayList<>();
        for (OrderSkuVO orderSkuVO : orderSkuList) {
            if (!orderIds.contains(orderSkuVO.getOrderId())) {
                orderIds.add(orderSkuVO.getOrderId());
            }
            if (!skuIds.contains(orderSkuVO.getSkuId())) {
                skuIds.add(orderSkuVO.getSkuId());
            }
            if (!tenantIds.contains(orderSkuVO.getTenantId())) {
                tenantIds.add(orderSkuVO.getTenantId());
            }
        }
        List<OrderResp> orderList = ordersMapper.findAllByIds(req.getUserId(), req.getShopId(), orderIds);

        List<Long> shopIds = new ArrayList<>();
        orderList.stream().forEach(item -> {
            if (item.getShopId() != null && !shopIds.contains(item.getShopId())) {
                shopIds.add(item.getShopId());
            }
        });

        // 获取商品sku信息
        Map<Long, Sku> skuMap = daoService.getSkuMap(skuIds);
        Map<Long, List<OrderSkuVO>> orderSkuMap = new HashMap<>();
        // 组装数据
        orderSkuList.stream().forEach((item) -> {
            item.setImage(skuMap.get(item.getSkuId()).getImage());
            item.setSpecNames(skuMap.get(item.getSkuId()).getSpecNames());
            item.setSpecValues(skuMap.get(item.getSkuId()).getSpecValues());
            item.setSpuType(skuMap.get(item.getSkuId()).getType());
            if (orderSkuMap.containsKey(item.getOrderId())) {
                orderSkuMap.get(item.getOrderId()).add(item);
            } else {
                List<OrderSkuVO> list = new ArrayList<>();
                list.add(item);
                orderSkuMap.put(item.getOrderId(), list);
            }
        });


        Map<Long, Shop> shopMap = shopIds.isEmpty() ? new HashMap<>() : daoService.getShopMap(shopIds);
        orderList.stream().forEach(item -> {
            item.setOrderSkuList(orderSkuMap.get(item.getId()));
            if (item.getShopId() != null) {
                item.setShopName(shopMap.get(item.getShopId()).getShopName());
                item.setShopAvatar(shopMap.get(item.getShopId()).getAvatar());
            }
            item.setTenantNickname(shopMap.get(item.getTenantId()).getShopName());
        });

        if (req.getShopId() != null) {
            Map<Long, User> userMap = daoService.getUserMap(orderList.stream().map(Orders::getUserId).collect(Collectors.toList()));
            orderList.stream().forEach(item -> {
                item.setUserNickname(userMap.get(item.getUserId()).getNickname());
                item.setUserAvatar(userMap.get(item.getUserId()).getAvatar());
            });
        }

        ResultData<BasePageResp<OrderResp>> resultData = PageHelpUtil.buildPage(orderList, page);
        resultData.getValue().setExtra(orderSkuMapper.sumPageAmount(req));

        return resultData;
    }

    @Override
    public ResultData<BasePageResp<OrderResp>> getOrderPage(User user, PageReq req) {
        req.setUserId(user.getId());
        req.setHidden(0);
        if (StringUtils.isEmpty(req.getName())) {
            return getOrderPageDefault(req);
        } else {
            return getOrderPageByName(req);
        }
    }

    @Override
    public ResultData<BasePageResp<OrderResp>> getShopOrderPage(User user, PageReq req) {
        req.setShopId(user.getShopId() == null ? -1L : user.getShopId());
        if (StringUtils.isEmpty(req.getName()) && StringUtils.isEmpty(req.getActivityType())) {
            return getOrderPageDefault(req);
        } else {
            return getOrderPageByName(req);
        }
    }

    @Override
    public ResultData<Long> getUserIdByNameOrPhone(User user, String param) {
        if (user.getShopId() == null) {
            return new ResultData<>(0L);
        }
        String phone = null;
        String name = null;
        if (StringUtils.isNumeric(param)) {
            phone = param;
        } else {
            name = param;
        }
        OrderAddressPageReq req = new OrderAddressPageReq(1, 10, phone, name);
        List<OrderAddress> orderAddressList = orderAddressMapper.findAllByPhoneAndName(req);
        if (orderAddressList.isEmpty()) {
            return new ResultData<>(0L);
        }
        return new ResultData<>(orderAddressList.get(0).getUserId());
    }

    @Override
    public ResultData<OrderDetailResp> getOrderDetail(User user, Long orderId) {
        ResultData<OrderDetailResp> resp = new ResultData<>();
        Orders orders = ordersMapper.selectByPrimaryKey(orderId);
        // 仅本人可以可见订单详情（本店用户也可以查看订单详情）
        if (!user.getId().equals(orders.getUserId())) {
            resp.setResultCode(ResultCode.FAIL);
            return resp;
        }
        OrderDetailResp orderDetailResp = getOrderDetailCommon(orders, orderId);
        orderDetailResp.setTenantNickname(tenantMapper.selectByPrimaryKey(orders.getTenantId()).getTenantNickname());
        resp.setValue(orderDetailResp);
        return resp;
    }

    @Override
    public ResultData<OrderDetailResp> getOrderDetailForShop(User user, Long orderId) {
        ResultData<OrderDetailResp> resp = new ResultData<>();
        Orders orders = ordersMapper.selectByPrimaryKey(orderId);
        // 仅店员可见
        if (!user.getShopId().equals(orders.getShopId()) && UserStaffTypeEnum.NOT_STAFF.getType().equals(user.getStaffType())) {
            resp.setResultCode(ResultCode.FAIL);
            return resp;
        }
        OrderDetailResp result = getOrderDetailCommon(orders, orderId);
        UserRelationship userRelationship = userRelationshipMapper.findOneBySubordinateId(orders.getUserId());
        if (userRelationship != null) {
            result.setSuperiorNickname(userMapper.selectByPrimaryKey(userRelationship.getSuperiorId()).getNickname());
        }
        resp.setValue(result);
        return resp;
    }

    OrderDetailResp getOrderDetailCommon(Orders orders, Long orderId) {
        // 获取订单商品明细列表
        List<OrderSkuVO> orderSkuList = orderSkuMapper.findAllByOrderId(orderId);
        List<Long> spuIds = new ArrayList<>();
        List<Long> skuIds = new ArrayList<>();
        orderSkuList.forEach(item -> {
            if (!spuIds.contains(item.getSpuId())) {
                spuIds.add(item.getSpuId());
            }
            skuIds.add(item.getSkuId());
        });

        Map<Long, List<OrderSkuVO>> orderSkuMap = new HashMap<>();

        // 获取商品sku信息
        Map<Long, Sku> skuMap = daoService.getSkuMap(skuIds);

        orderSkuList.stream().forEach((item) -> {
            item.setImage(skuMap.get(item.getSkuId()).getImage());
            item.setSpecNames(skuMap.get(item.getSkuId()).getSpecNames());
            item.setSpecValues(skuMap.get(item.getSkuId()).getSpecValues());

            if (orderSkuMap.containsKey(item.getOrderId())) {
                orderSkuMap.get(item.getOrderId()).add(item);
            } else {
                List<OrderSkuVO> list = new ArrayList<>();
                list.add(item);
                orderSkuMap.put(item.getOrderId(), list);
            }
        });

        OrderDetailResp orderDetailResp = new OrderDetailResp();
        BeanUtils.copyProperties(orders, orderDetailResp);
        OrderAddress orderAddress = orderAddressMapper.findOneByOrderId(orderId);
        orderDetailResp.setOrderAddress(orderAddressMapper.findOneByOrderId(orderId));
        orderDetailResp.setOrderDiscountList(orderDiscountMapper.findAllByOrderId(orderId));
        orderDetailResp.setOrderSkuList(orderSkuList);
        if (orders.getLogisticsNumber() != null && !"OTHER".equals(orders.getLogisticsCompany())) {
            try {
                orderDetailResp.setLogisticsTrace(logisticsService.getOrderTracesByJson(orders.getTradeNo(), orders.getLogisticsCompany(), orders.getLogisticsNumber(), orderAddress.getPhone()));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        // 如果是预约订单，则生成核销二维码
        if (OrderTypeEnum.ONLINE_SELF.getType().equals(orders.getOrderType())) {
            Hashids hashids = new Hashids(salt, 32);
            String orderSpuHashId = hashids.encode(orderSkuList.get(0).getId());
            orderDetailResp.setHashId(orderSpuHashId);
        }

        // 获取商家信息
        if (orders.getShopId() != null) {
            Shop shop = shopMapper.selectByPrimaryKey(orders.getShopId());
            orderDetailResp.setShopName(shop.getShopName());
            orderDetailResp.setShopAvatar(shop.getAvatar());
            orderDetailResp.setShopPhone(shop.getPhone());
        }

        // 获取核销店员信息
        if (orderSkuList.get(0).getVerifyClerkId() != null) {
            orderSkuList.get(0).setVerifyNickname(userMapper.selectByPrimaryKey(orderSkuList.get(0).getVerifyClerkId()).getNickname());
        }

        // 获取用户的昵称和手机号
        User user = userMapper.selectByPrimaryKey(orders.getUserId());
        orderDetailResp.setUserAvatar(user.getAvatar());
        orderDetailResp.setUsername(user.getUsername());
        orderDetailResp.setUserNickname(user.getNickname());

        //获取优惠券信息
        OrderDiscount orderDiscount = orderDiscountMapper.findOneByOrderIdAndType(orderId, PromotionEnum.COUPON.getPromotion());
        if (orderDiscount != null) {
            orderDetailResp.setCoupon(couponMapper.selectByPrimaryKey(orderDiscount.getRelateId()));
        }
        return orderDetailResp;
    }

    @Override
    public BaseResp deleteOrders(User user, Long id) {
        ordersMapper.updateHiddenAndUpdatedAtByIdAndUserId(HiddenEnum.HIDDEN.getStatus(), new Date(), id, user.getId());
        return new BaseResp();
    }

    @Override
    public ResultData<OrderComment> getOrderCommentDetail(User user, Long orderSkuId) {
        return new ResultData<>(orderCommentMapper.findOneByOrderSkuIdAndUserId(orderSkuId, user.getId()));
    }

    public static void calcStarCount(CommentStatistics target, Byte star, Integer num) {
        switch (star) {
            case (byte) 1:
                target.setOne(target.getOne() + num);
                break;
            case (byte) 2:
                target.setTwo(target.getTwo() + num);
                break;
            case (byte) 3:
                target.setThree(target.getThree() + num);
                break;
            case (byte) 4:
                target.setFour(target.getFour() + num);
                break;
            case (byte) 5:
                target.setFive(target.getFive() + num);
                break;
            default:
                break;
        }
    }


    @Override
    public BaseResp editOrderComment(User user, OrderComment orderComment) {
        // 添加评价
        OrderSku orderSku = orderSkuMapper.selectByPrimaryKey(orderComment.getOrderSkuId());

        if (orderComment.getId() == null) {


            // 如果待评价或已完成，则可以评价
            if (OrdersStatusEnum.COMMENT.getStatus().equals(orderSku.getStatus()) || OrdersStatusEnum.DONE.getStatus().equals(orderSku.getStatus())) {
                orderComment.setOrderId(orderSku.getOrderId());
                orderComment.setUserId(user.getId());
                orderComment.setSpuId(orderSku.getSpuId());
                orderComment.setSkuId(orderSku.getSkuId());
                orderComment.setStatus(OrderCommentStatusEnum.NORMAL.getStatus());
                orderComment.setShopId(orderSku.getShopId());
                orderComment.setCreatedAt(new Date());
                orderComment.setUpdatedAt(new Date());

                orderCommentMapper.insert(orderComment);

                // 增加评价统计数量
                CommentStatistics commentStatistics = commentStatisticsMapper.findOneBySpuId(orderSku.getSpuId());

                // fix 如果一些商品没创建初始的评价统计，则补创建一个
                if (commentStatistics == null) {
                    // 初始化spu评价统计
                    commentStatistics = new CommentStatistics(null, orderSku.getSpuId(), 0, 0, 0, 0, 0, 0, 0, 0);
                    commentStatisticsMapper.insert(commentStatistics);
                }

                commentStatistics.setDefaultFive(commentStatistics.getDefaultFive() - 1);
                if (!orderComment.getStar().equals((byte) 5)) {
                    commentStatistics.setFive(commentStatistics.getFive() - 1);
                    calcStarCount(commentStatistics, orderComment.getStar(), 1);
                }
                if (orderComment.getImageList() != null) {
                    commentStatistics.setHasImage(commentStatistics.getHasImage() + 1);
                }

                commentStatisticsMapper.updateByPrimaryKey(commentStatistics);
                spuMapper.updateFiveStarById(commentStatistics.getFive(), commentStatistics.getSpuId());

                // 已完成：仅表示已评价，但评价可能是默认评价
                orderSkuMapper.updateCommentIdById(orderComment.getId(), OrdersStatusEnum.DONE.getStatus(), orderSku.getId());

                // 如果所有商品都评价了，那么总订单也要改成已完成状态
                List<OrderSkuVO> orderSkuList = orderSkuMapper.findAllByOrderId(orderSku.getOrderId());
                if (orderSkuList.size() == 1) {
                    // 那么所有商品都评价了
                    ordersMapper.updateStatusById(OrdersStatusEnum.DONE.getStatus(), orderSku.getOrderId());
                } else {
                    boolean isAllComment = true;
                    for (OrderSkuVO orderSkuVO : orderSkuList) {
                        if (orderSkuVO.getCommentId() == null) {
                            isAllComment = false;
                        }
                    }
                    if (isAllComment) {
                        ordersMapper.updateStatusById(OrdersStatusEnum.DONE.getStatus(), orderSku.getOrderId());
                    }
                }
            } else {
                new BaseResp(ResultCode.FAIL);
            }
        } else {
            OrderComment result = orderCommentMapper.selectByPrimaryKey(orderComment.getId());
            // 判断之前的星级和当前的星级是否一样，如果不一样，则变更统计数量

            boolean isStarChange = !result.getStar().equals(orderComment.getStar());
            boolean isImageAdd = result.getImageList() == null && orderComment.getImageList() != null;
            boolean isImageDelete = result.getImageList() != null && orderComment.getImageList() == null;
            if (isStarChange || isImageAdd || isImageDelete) {
                CommentStatistics commentStatistics = commentStatisticsMapper.findOneBySpuId(result.getSpuId());

                if (isStarChange) {
                    // 之前星级-1
                    calcStarCount(commentStatistics, result.getStar(), -1);
                    // 当前星级+1
                    calcStarCount(commentStatistics, orderComment.getStar(), 1);
                }

                if (isImageAdd) {
                    commentStatistics.setHasImage(commentStatistics.getHasImage() + 1);
                }

                if (isImageDelete) {
                    commentStatistics.setHasImage(commentStatistics.getHasImage() - 1);
                }

                commentStatisticsMapper.updateByPrimaryKey(commentStatistics);
                spuMapper.updateFiveStarById(commentStatistics.getFive(), commentStatistics.getSpuId());
            }

            // 修改评价，但不可以修改状态
            orderComment.setStatus(null);
            orderComment.setUpdatedAt(new Date());

            // 如果原先有图片，修改时全部删除了，则要单独更新
            if (isImageDelete) {
                orderCommentMapper.updateImageListById(null, orderComment.getId());
            }

            if (orderComment.getVideo() == null) {
                orderComment.setVideo("");
            }
            orderCommentMapper.updateByPrimaryKeySelective(orderComment);
        }


        if (OrderTypeEnum.ONLINE_SELF.getType().equals(orderSku.getOrderType())) {
            // 如果是门店商品，则更新此商店的评价统计
            StarStatisticsVO starStatisticsVO = orderCommentMapper.avgByShopId(orderSku.getShopId());

            if (starStatisticsVO == null) {
                starStatisticsVO = StarStatisticsVO.builder().overallStarAvg(new BigDecimal(BigInteger.ZERO)).serviceStarAvg(new BigDecimal(BigInteger.ZERO)).environmentStarAvg(new BigDecimal(BigInteger.ZERO)).valueStarAvg(new BigDecimal(BigInteger.ZERO)).build();
            } else {
                if (starStatisticsVO.getOverallStarAvg() == null) {
                    starStatisticsVO.setOverallStarAvg(new BigDecimal(BigInteger.ZERO));
                }
                if (starStatisticsVO.getServiceStarAvg() == null) {
                    starStatisticsVO.setServiceStarAvg(new BigDecimal(BigInteger.ZERO));
                }
                if (starStatisticsVO.getEnvironmentStarAvg() == null) {
                    starStatisticsVO.setEnvironmentStarAvg(new BigDecimal(BigInteger.ZERO));
                }
                if (starStatisticsVO.getValueStarAvg() == null) {
                    starStatisticsVO.setValueStarAvg(new BigDecimal(BigInteger.ZERO));
                }
            }
            Shop shop = shopMapper.selectByPrimaryKey(orderSku.getShopId());
            shop.setOverallStar(starStatisticsVO.getOverallStarAvg().setScale(2, BigDecimal.ROUND_HALF_DOWN));
            shop.setServiceStar(starStatisticsVO.getServiceStarAvg().setScale(2, BigDecimal.ROUND_HALF_DOWN));
            shop.setEnvironmentStar(starStatisticsVO.getEnvironmentStarAvg().setScale(2, BigDecimal.ROUND_HALF_DOWN));
            shop.setValueStar(starStatisticsVO.getValueStarAvg().setScale(2, BigDecimal.ROUND_HALF_DOWN));
            shopMapper.updateByPrimaryKeySelective(shop);
        }

        // 清空商品缓存
        deleteRedisByKey("ProductDetail:" + orderComment.getSpuId() + ":*");
        return new BaseResp();
    }


    private void deleteRedisByKey(String key) {
        Set<String> keys = redisTemplate.keys(key);
        if (!CollectionUtils.isEmpty(keys)) {
            redisTemplate.delete(keys);
        }
    }

    @Override
    public BaseResp toggleOrderComment(User user, Long id) {
        OrderComment orderComment = orderCommentMapper.selectByPrimaryKey(id);
        if (!user.getId().equals(orderComment.getUserId())) {
            return new BaseResp(ResultCode.FAIL);
        }

        // 已经被客服关闭的，不可以再开启或关闭
        if (OrderCommentStatusEnum.OFFICE_CLOSE.getStatus().equals(orderComment.getStatus())) {
            return new BaseResp(ResultCode.FAIL);
        }

        orderComment.setStatus(OrderCommentStatusEnum.NORMAL.getStatus().equals(orderComment.getStatus()) ? OrderCommentStatusEnum.CUSTOMER_CLOSE.getStatus() : OrderCommentStatusEnum.NORMAL.getStatus());
        orderCommentMapper.updateByPrimaryKey(orderComment);

        deleteRedisByKey("ProductDetail:" + orderComment.getSpuId() + ":*");

        return new BaseResp();
    }

    @Override
    public BaseResp deleteComment(User user, Long id) {
        OrderComment orderComment = orderCommentMapper.selectByPrimaryKey(id);
        if (!user.getId().equals(orderComment.getUserId())) {
            return new BaseResp(ResultCode.FAIL);
        }
        orderCommentMapper.deleteByPrimaryKey(id);

        deleteRedisByKey("ProductDetail:" + orderComment.getSpuId() + ":*");
        return new BaseResp();
    }

    private BigDecimal getOrderSkuCouponAmount(OrderDiscount orderDiscount, AfterSale afterSale, OrderSku orderSku) {
        Coupon coupon = couponMapper.selectByPrimaryKey(orderDiscount.getRelateId());
        BigDecimal eachCouponAmount = BigDecimal.ZERO;
        if (OrderDiscountLevelEnum.ORDER_LEVEL.getType().equals(orderDiscount.getLevel())) {
            //订单级优惠券
            List<OrderSkuVO> orderSkuVOList = orderSkuMapper.findAllByOrderId(afterSale.getOrderId());
            BigDecimal totalPayAmount = orderSkuVOList.stream().map(item -> item.getPayAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
            //orderSku分摊优惠券金额
            eachCouponAmount = orderSku.getPayAmount().divide(totalPayAmount, 6, BigDecimal.ROUND_HALF_DOWN).multiply(coupon.getDiscountAmount()).setScale(2, BigDecimal.ROUND_HALF_DOWN);
        } else if (OrderDiscountLevelEnum.SPU_LEVEL.getType().equals(orderDiscount.getLevel())) {
            //商品级优惠券
            if (afterSale.getSpuId().equals(coupon.getSpuId())) {
                eachCouponAmount = coupon.getDiscountAmount();
            }
        }
        return eachCouponAmount;
    }

    @Override
    public BaseResp editAfterSale(User user, AfterSale afterSale) {
        afterSale.setUserId(user.getId());

        Orders orders = ordersMapper.selectByPrimaryKey(afterSale.getOrderId());
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -7);
        if (orders.getCompleteTime() != null && orders.getCompleteTime().before(calendar.getTime())) {
            return new BaseResp(ResultCode.AFTER_SALE_BEFORE_7_DAY);
        }

        // 判断此订单是否属于此用户
        OrderSku orderSku = orderSkuMapper.selectByPrimaryKey(afterSale.getOrderSkuId());
        if (orderSku == null || !user.getId().equals(orderSku.getUserId()) || !orderSku.getOrderId().equals(afterSale.getOrderId())) {
            return new BaseResp(ResultCode.FAIL);
        }

        if (afterSale.getCount() > orderSku.getCount()) {
            return new BaseResp(ResultCode.AFTER_SALE_COUNT_OVER);
        }

        //仅退款或退货退款
        if (AfterSaleTypeEnum.ONLY_REFUND.getType().equals(afterSale.getType()) || AfterSaleTypeEnum.RETURN_REFUND.getType().equals(afterSale.getType())) {
            BigDecimal applyAmount = afterSale.getApplyAmount();
            OrderDiscount orderDiscount = orderDiscountMapper.findOneByOrderIdAndType(afterSale.getOrderId(), PromotionEnum.COUPON.getPromotion());
            //使用了优惠券折扣
            if (orderDiscount != null) {
                BigDecimal maxRefundAmount = orderSku.getPayAmount().add(orders.getTotalFreight()).subtract(getOrderSkuCouponAmount(orderDiscount, afterSale, orderSku));
                if (applyAmount.compareTo(maxRefundAmount) > 0) {
                    return new BaseResp(ResultCode.REFUND_AMOUNT_OVER_MAX);
                }
            }

            if (orders.getTotalRefundAmount().add(afterSale.getApplyAmount()).compareTo(orders.getTotalPayAmount()) > 0) {
                return new BaseResp(ResultCode.OVER_PAID);
            }
        }

        afterSale.setShopId(orderSku.getShopId());
        afterSale.setOrderType(orderSku.getOrderType());
        afterSale.setSkuId(orderSku.getSkuId());
        afterSale.setSpuId(orderSku.getSpuId());
        afterSale.setTradeNo(orders.getTradeNo());
        afterSale.setRefundAmount(BigDecimal.ZERO);
        afterSale.setRefundTime(new Date());
        afterSale.setCreatedAt(new Date());
        afterSale.setUpdatedAt(new Date());
        afterSale.setStatus(AfterSaleStatusEnum.PROCESSING.getStatus());
        afterSale.setHidden(HiddenEnum.VISIBLE.getStatus());
        afterSale.setProductName(spuMapper.selectByPrimaryKey(orderSku.getSpuId()).getName());
        afterSale.setTenantId(orderSku.getTenantId());


        BigDecimal tenantRefund = BigDecimal.ZERO;
        if (orderSku.getTenantAmount().compareTo(BigDecimal.ZERO) > 0) {
            tenantRefund = afterSale.getApplyAmount().multiply(orderSku.getTenantAmount().divide(orderSku.getPayAmount(), 2, BigDecimal.ROUND_HALF_DOWN)).setScale(2, BigDecimal.ROUND_HALF_DOWN);
        }
        afterSale.setTenantAmount(tenantRefund);

        if (afterSale.getId() == null) {
            // 先判断此订单sku有没有申请过售后
            AfterSale result = afterSaleMapper.findOneByOrderSkuIdAndUserId(afterSale.getOrderSkuId(), user.getId());
            if (result != null) {
                return new BaseResp(ResultCode.FAIL);
            }
            afterSaleMapper.insert(afterSale);
            orderSkuMapper.updateAfterSaleIdById(afterSale.getId(), orderSku.getId());
        } else {
            AfterSale result = afterSaleMapper.selectByPrimaryKey(afterSale.getId());
            // 只有待审核可以修改
            if (AfterSaleStatusEnum.PROCESSING.getStatus().equals(result.getStatus())) {
                afterSaleMapper.updateByPrimaryKey(afterSale);
            } else {
                return new BaseResp(ResultCode.FAIL);
            }
        }
        return new BaseResp();
    }

    @Override
    public BaseResp editAfterSaleLogistics(User user, AfterSale afterSale) {
        AfterSale result = afterSaleMapper.selectByPrimaryKey(afterSale.getId());
        // 先判断是否属性本人的售后
        if (user.getId().equals(result.getUserId())) {
            // 更新退货物流信息
            result.setReturnLogisticsCompany(afterSale.getReturnLogisticsCompany());
            result.setReturnLogisticsNumber(afterSale.getReturnLogisticsNumber());
            afterSaleMapper.updateByPrimaryKeySelective(result);
        } else {
            return new BaseResp(ResultCode.FAIL);
        }
        return new BaseResp();
    }

    @Override
    public ResultData<AfterSale> getAfterSale(User user, Long id) {
        return new ResultData<>(afterSaleMapper.findOneByIdAndUserId(id, user.getId()));
    }

    @Override
    public BaseResp cancelAfterSale(User user, Long id) {
        // 只有 已申请售后，同意售后申请待退货两种状态，可以取消售后
        AfterSale afterSale = afterSaleMapper.findOneByIdAndUserId(id, user.getId());
        Boolean canCancel = AfterSaleStatusEnum.PROCESSING.getStatus().equals(afterSale.getStatus()) || AfterSaleStatusEnum.CONFIRM.getStatus().equals(afterSale.getStatus());
        if (afterSale == null || !canCancel) {
            return new BaseResp(ResultCode.FAIL);
        }

        afterSale.setStatus(AfterSaleStatusEnum.CANCEL.getStatus());
        afterSale.setUpdatedAt(new Date());
        afterSaleMapper.updateByPrimaryKey(afterSale);
        return new BaseResp();
    }

    @Override
    public ResultData<BasePageResp<AfterSaleResp>> getAfterSalePage(User user, PageReq req) {
        req.setUserId(user.getId());
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<AfterSaleResp> list = afterSaleMapper.findAllFrontPage(req);
        if (CollectionUtils.isEmpty(list)) {
            return PageHelpUtil.buildPage(list, page);
        }
        List<Long> skuIds = new ArrayList<>();
        list.forEach(item -> {
            if (!skuIds.contains(item.getSkuId())) {
                skuIds.add(item.getSkuId());
            }
        });

        // 获取商品sku信息
        Map<Long, Sku> skuMap = daoService.getSkuMap(skuIds);

        list.stream().forEach((item) -> {
            item.setImage(skuMap.get(item.getSkuId()).getImage());
            item.setSpecNames(skuMap.get(item.getSkuId()).getSpecNames());
            item.setSpecValues(skuMap.get(item.getSkuId()).getSpecValues());
        });
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public ResultData<String> getLogisticsTrace(User user, Long orderId) {
        Orders orders = ordersMapper.selectByPrimaryKey(orderId);
        if (orders.getUserId().equals(user.getId())) {
            try {
                OrderAddress orderAddress = orderAddressMapper.findOneByOrderId(orderId);
                String result = logisticsService.getOrderTracesByJson(orders.getTradeNo(), orders.getLogisticsCompany(), orders.getLogisticsNumber(), orderAddress.getPhone());
                return new ResultData<>(result);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return new ResultData<>("[]");
    }

    @Override
    public ResultData<LogisticsAndAddressVO> getLogisticsTraceAndAddress(User user, Long orderId) {
        LogisticsAndAddressVO vo = new LogisticsAndAddressVO();
        Orders orders = ordersMapper.selectByPrimaryKey(orderId);
        if (orders.getUserId().equals(user.getId()) || orders.getTenantId().equals(user.getShopId())) {
            try {
                OrderAddress orderAddress = orderAddressMapper.findOneByOrderId(orderId);
                String result = logisticsService.getOrderTracesByJson(orders.getTradeNo(), orders.getLogisticsCompany(), orders.getLogisticsNumber(), orderAddress.getPhone());
                vo.setTrace(result);
            } catch (Exception e) {
                vo.setTrace("[]");
                e.printStackTrace();
            }
        } else {
            vo.setTrace("[]");
        }
        vo.setOrderAddress(orderAddressMapper.findOneByOrderId(orderId));
        return new ResultData<>(vo);
    }

    @Override
    public ResultData<OrderSkuAndOrderAddressVO> getOrderSkuAndOrderAddress(User user, Long orderSkuId) {
        OrderSkuAndOrderAddressVO vo = new OrderSkuAndOrderAddressVO();
        OrderSku orderSku = orderSkuMapper.selectByPrimaryKey(orderSkuId);
        Orders orders = ordersMapper.selectByPrimaryKey(orderSku.getOrderId());
        if (orderSku.getUserId().equals(user.getId())) {
            vo.setTotalFreight(orders.getTotalFreight());
            vo.setOrderSku(orderSku);
            vo.setOrderAddress(orderAddressMapper.findOneByOrderId(orderSku.getOrderId()));
        }
        return new ResultData<>(vo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResp confirmOrder(User user, Long orderId) {
        Orders orders = ordersMapper.selectByPrimaryKey(orderId);
        if (user.getId().equals(orders.getUserId()) && OrdersStatusEnum.PAID.getStatus().equals(orders.getStatus())) {
            commonOrderService.confirmOrderFreeze(orders);
            List<OrderSkuVO> orderSkuList = orderSkuMapper.findAllByOrderId(orderId);
            // 是否为分享赚订单
            if (CollectionUtils.isNotEmpty(orderSkuList)) {
                shareRebate(orderSkuList);
            }
            return new BaseResp();
            // 购买指定SPU商品 赠送抽奖机会
//            String value = webConfigMapper.findValueByName(WebConfigEnum.GIVE_OPPORTUNITY_SPU.getConfig());
//            if (!StringUtils.isEmpty(value)) {
//                String[] split = value.split(",");
//                if (split != null && split.length > 0) {
//                    List<LotteryOpportunity> lotteryOpportunityList = new ArrayList<>();
//                    //赠送机会商品编号
//                    List<Long> spuIds = new ArrayList<>();
//                    for (String s : split) {
//                        spuIds.add(Long.valueOf(s));
//                    }
//
//                    if (orderSkuList.size() > 0) {
//                        orderSkuList.stream().forEach(item -> {
//                            LotteryOpportunity lotteryOpportunity = LotteryOpportunity.builder().userId(user.getId()).relateId(orderId).type(LotteryOpportunityTypeEnum.SPU_GIVE.getType()).status(LotteryOpportunityStatusEnum.NOT_USED.getStatus()).remark(item.getProductName()).createdAt(new Date()).updatedAt(new Date()).build();
//                            if (spuIds.contains(item.getSpuId())) {
//                                for (int i = 0; i < item.getCount(); i++) {
//                                    lotteryOpportunityList.add(lotteryOpportunity);
//                                }
//                            }
//                        });
//                    }
//
//                    //一次机会一条记录
//                    if (lotteryOpportunityList.size() > 0) {
//                        lotteryOpportunityMapper.batchInsert(lotteryOpportunityList);
//                    }
//                }
//            }
        }
        return new BaseResp(ResultCode.FAIL);
    }

    private void shareRebate(List<OrderSkuVO> orderSkuList) {
        Map<String, String> hipoConfigMap = daoService.getHipoConfigMap();
        orderSkuList.forEach(orderSkuVO -> {
            if (orderSkuVO.isShare()) {
                List<ShareDetailedVo> detailedVos = shareDetailedMapper.getDetailedByOrderSkuId(orderSkuVO.getId());
                if (CollectionUtils.isNotEmpty(detailedVos)) {
                    Date date = new Date();
                    detailedVos.forEach(detailedVo -> {
                        if (!detailedVo.isIssued()) {
                            ShareActivity activity = shareActivityMapper.getByShareActivityId(detailedVo.getShareActivityId());
                            if (activity.getConfirmReceipt()) {
                                OrderSku orderSku = orderSkuMapper.findOneById(detailedVo.getOrderSkuId());
                                detailedVo.setReceiptTime(date);
                                detailedVo.setIssued(true);
                                detailedVo.setUpdated(date);
                                // 修改数据到账时间
                                shareDetailedMapper.updateByPrimaryKey(detailedVo);
                                // 发放佣金
                                shareActivityService.provide(ObjectUtil.copy(detailedVo, ShareDetailed.class), orderSku);
                            } else {
                                // 计算佣金/嗨币到账时间
                                Long hours = Long.parseLong(hipoConfigMap.get(HipoConfigEnum.RECEIPT_TIME.getConfig()));
                                LocalDateTime localDateTime = LocalDateTime.now().plusDays(hours);
                                // 到账时间
                                Date receiptTime = DateConvertUtil.LocalDateTimeToDate(localDateTime);
                                detailedVo.setReceiptTime(receiptTime);
                                detailedVo.setUpdated(date);
                                // 修改数据到账时间
                                shareDetailedMapper.updateByPrimaryKey(detailedVo);
                                // 加入定时任务
                                miniShareDetailedTask.addTask(detailedVo);
                            }
                        }
                    });
                }
            }
        });
    }

    @Override
    public ResultData<OrderQrcodeInfoVO> getOrderQrcodeInfo(PageReq req) {

        OrderQrcodeInfoVO vo = new OrderQrcodeInfoVO();
        OrderSku orderSku = orderSkuMapper.selectByPrimaryKey(req.getId());

        if (OrdersStatusEnum.COMMENT.getStatus().equals(orderSku.getStatus()) || OrdersStatusEnum.DONE.getStatus().equals(orderSku.getStatus())) {
            vo.setIsVerify(true);
            req.setPageNo(1);
            req.setPageSize(2);
        } else {
            vo.setIsVerify(false);
            req.setPageNo(1);
            req.setPageSize(2);
        }

        PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<Shop> shopList = shopMapper.findAllNearbyPage(req);

        // 防止被人遍历核销
        Hashids hashids = new Hashids(salt, 32);
        String orderSpuHashId = hashids.encode(orderSku.getId());
        vo.setHashId(orderSpuHashId);
        vo.setShopList(shopList);
        vo.setOrderSku(orderSku);

        return new ResultData<>(vo);
    }

    @Override
    public ResultData<OrderSkuVO> verifyOrderInfoByHashId(String hashId) {
        Hashids hashids = new Hashids(salt, 32);
        Long id = hashids.decode(hashId)[0];
        OrderSku orderSku = orderSkuMapper.selectByPrimaryKey(id);
        OrderSkuVO orderSkuVO = new OrderSkuVO();
        BeanUtils.copyProperties(orderSku, orderSkuVO);
        Sku sku = skuMapper.selectByPrimaryKey(orderSku.getSkuId());
        orderSkuVO.setImage(sku.getImage());
        orderSkuVO.setStockUnit(sku.getStockUnit());
        orderSkuVO.setOrderCount(orderSkuMapper.countByUserIdAndTenantIdAndStatus(orderSku.getUserId(), orderSku.getTenantId()));
        orderSkuVO.setShopName(shopMapper.selectByPrimaryKey(orderSku.getTenantId()).getShopName());
        return new ResultData<>(orderSkuVO);
    }

    @Override
    public BaseResp verifyConfirmOrderSku(String hashId) {
        Hashids hashids = new Hashids(salt, 32);
        Long id = hashids.decode(hashId)[0];
        OrderSku orderSku = orderSkuMapper.selectByPrimaryKey(id);

        // 判断商品是否处理有效状态
        if (!OrdersStatusEnum.PAID.getStatus().equals(orderSku.getStatus())) {
            return new BaseResp(ResultCode.FAIL);
        }

        // 先判断商品是否已经核销，
        if (OrderSkuVerifyStatusEnum.NOT_VERIFY.getStatus().equals(orderSku.getVerifyStatus())) {
            // 再判断此商店内是否还有库存
            User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            if (user.getShopId() == null || !user.getShopId().equals(orderSku.getShopId())) {
                return new BaseResp(ResultCode.NOT_PERMISSION_VERIFY);
            }

            // 修改此商品订单状态
            orderSku.setStatus(OrdersStatusEnum.COMMENT.getStatus());
            orderSku.setVerifyStatus(OrderSkuVerifyStatusEnum.HAS_VERIFY.getStatus());
            orderSku.setVerifyTime(new Date());
            orderSku.setVerifyShopId(user.getShopId());
            orderSku.setVerifyClerkId(user.getId());
            orderSkuMapper.updateByPrimaryKeySelective(orderSku);

            // 如果所有的商品都已经是已完成，则总订单也变更为已完成
            if (orderSkuMapper.countByUserIdAndOrderIdNotDone(orderSku.getUserId(), orderSku.getOrderId()) == 0) {
                commonOrderService.confirmOrder(ordersMapper.selectByPrimaryKey(orderSku.getOrderId()));
            }
            return new BaseResp();
        } else {
            return new BaseResp(ResultCode.ORDER_SKU_HAS_VERIFY);
        }
    }

    @Override
    public ResultData<BasePageResp<UserCommissionResp>> getFriendOrderPage(User user, UserCommissionReq req) {
        req.setSuperiorId(user.getId());
        req.setType(UserCommissionTypeEnum.SHARE.getType());
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<UserCommissionResp> list = userCommissionMapper.findAllPage(req);
        if (!CollectionUtils.isEmpty(list)) {
            List<OrderSku> orderSkus = orderSkuMapper.findAllByIds(list.stream().map(UserCommission::getOrderSkuId).collect(Collectors.toList()));

            Map<Long, OrderSku> orderSkuMap = new HashMap<>();
            orderSkus.stream().forEach(item -> orderSkuMap.put(item.getId(), item));

            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(UserCommission::getSubordinateId).collect(Collectors.toList()));

            list.stream().forEach((item) -> {
                item.setSubordinateNickname(userMap.get(item.getSubordinateId()).getNickname());
                item.setSubordinateAvatar(userMap.get(item.getSubordinateId()).getAvatar());
                item.setSubordinatePhone(userMap.get(item.getSubordinateId()).getUsername());
                item.setProductName(orderSkuMap.get(item.getOrderSkuId()).getProductName());
                item.setStatus(orderSkuMap.get(item.getOrderSkuId()).getStatus());
            });
        }
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public ResultData<BasePageResp<OrderSkuRecommendVO>> getShopOrderRecommendPage(PageReq req) {
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Long shopId = getUserShopId(user);
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        req.setShopId(shopId);
        List<OrderSkuRecommendVO> list = orderSkuMapper.findAllPage(req);
        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(OrderSkuRecommendVO::getInviteUserId).collect(Collectors.toList()));
            list.stream().forEach(item -> {
                item.setUserAvatar(userMap.get(item.getInviteUserId()).getAvatar());
                item.setUserNickname(userMap.get(item.getInviteUserId()).getNickname());
            });
        }
        ResultData<BasePageResp<OrderSkuRecommendVO>> result = PageHelpUtil.buildPage(list, page);
        BigDecimal bigDecimal = orderSkuMapper.getOrderMoney(req);
        result.getValue().setExtra(bigDecimal);
        return result;
    }

    @Override
    public ResultData<BasePageResp<OrderSkuRecommendVO>> getUserRecommendPage(PageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        req.setUserId(user.getId());
        List<OrderSkuRecommendVO> list = orderSkuMapper.findAllPage(req);
        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(OrderSkuRecommendVO::getUserId).collect(Collectors.toList()));
            Map<Long, Shop> shopMap = daoService.getShopMap(list.stream().map(OrderSkuRecommendVO::getShopId).collect(Collectors.toList()));
            list.stream().forEach(item -> {
                item.setUserAvatar(userMap.get(item.getUserId()).getAvatar());
                item.setUserNickname(userMap.get(item.getUserId()).getNickname());
                if (shopMap.containsKey(item.getShopId())) {
                    item.setShopName(shopMap.get(item.getShopId()).getShopName());
                }
            });
        }
        BigDecimal bigDecimal = orderSkuMapper.getOrderMoney(req);
        ResultData<BasePageResp<OrderSkuRecommendVO>> result = PageHelpUtil.buildPage(list, page);
        result.getValue().setExtra(bigDecimal);
        return result;
    }

    @Override
    public BaseResp updateOrderNameAndPhone(Orders req) {
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        ordersMapper.updateNameAndPhoneByIdAndUserId(req.getName(), req.getPhone(), req.getId(), user.getId());
        return new BaseResp();
    }

    @Override
    public ResultData<AnotherPayOrderVO> anotherPayOrderDetail(Long orderId) {

        Orders orders = ordersMapper.selectByPrimaryKey(orderId);

        if (orders != null && PayTypeEnum.ANOTHER_APY.getType().equals(orders.getPayType())) {
            if (orders.getCreatedAt().getTime() > (System.currentTimeMillis() - 24 * 3600000)) {
                User user = userMapper.selectByPrimaryKey(orders.getUserId());
                List<OrderSkuVO> orderSkuVOList = orderSkuMapper.findAllByOrderId(orderId);
                AnotherPayOrderVO payOrder = AnotherPayOrderVO.builder().orders(ordersMapper.selectByPrimaryKey(orderId)).phone(user.getUsername()).nickname(user.getNickname()).productName(orderSkuVOList.get(0).getProductName()).count(orderSkuVOList.size()).build();
                return new ResultData<>(payOrder);
            } else {
                ResultData<AnotherPayOrderVO> resultData = new ResultData<>();
                resultData.setResultCode(ResultCode.ANOTHER_PAY_INVALID);
                return resultData;
            }
        }

        return new ResultData<>(null);
    }

    @Override
    public ResultData<ReturnPayInfoVO> payForOtherOrder(User user, Long orderId, HttpServletRequest httpServletRequest) {
        Orders orders = ordersMapper.selectByPrimaryKey(orderId);

        if (orders != null && PayTypeEnum.ANOTHER_APY.getType().equals(orders.getPayType())) {
            if (OrdersStatusEnum.UNPAY.getStatus().equals(orders.getStatus())) {
                if (orders.getCreatedAt().getTime() > (System.currentTimeMillis() - 24 * 3600000)) {
                    List<OrderSkuVO> orderSkuVOList = orderSkuMapper.findAllByOrderId(orderId);
                    ReturnPayInfoVO infoVO = new ReturnPayInfoVO();
                    // 微信支付
                    if (orders.getTotalPayAmount().compareTo(BigDecimal.ZERO) > 0) {
                        // 更新tradeNo，以便每次都能调起微信支付
                        String tradeNo = Long.toString(uidGenerator.getUID());
                        ordersMapper.updateTradeNoById(tradeNo, orderId);

                        // 创建微信支付
                        final WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = WxPayUnifiedOrderRequest.newBuilder().openid(user.getOpenid()).outTradeNo(tradeNo)
                                //订单金额, 单位：分
                                .totalFee(orders.getTotalPayAmount().multiply(new BigDecimal(100)).intValue()).body(StringHelper.subPayBodyString(orderSkuVOList.get(0).getProductName() + (orderSkuVOList.size() > 1 ? "等" + orderSkuVOList.size() + "件商品" : ""))).spbillCreateIp(IpUtil.getIpAddr(httpServletRequest)).notifyUrl(domainUrl + "/api/order/wechatOrderNotify").build();
                        infoVO = commonService.getReturnPayInfoVO(wxPayUnifiedOrderRequest);


                        // 创建代付记录
                        OrderPay orderPay = orderPayMapper.findOneByOrderIdAndPayUserId(orderId, user.getId());
                        if (orderPay == null) {
                            orderPayMapper.insert(OrderPay.builder().orderUserId(orders.getUserId()).payUserId(user.getId()).orderId(orderId).status(OrderPayStatusEnum.NOT_PAY.getStatus()).remark(orderSkuVOList.get(0).getProductName() + (orderSkuVOList.size() > 1 ? "等" + orderSkuVOList.size() + "件商品" : "")).createdAt(new Date()).updatedAt(new Date()).tradeNo(tradeNo).build());
                        } else {
                            orderPay.setTradeNo(tradeNo);
                            orderPayMapper.updateByPrimaryKeySelective(orderPay);
                        }
                        return new ResultData<>(infoVO);
                    }
                } else {
                    ResultData<ReturnPayInfoVO> resultData = new ResultData<>();
                    resultData.setResultCode(ResultCode.ANOTHER_PAY_INVALID);
                    return resultData;
                }
            } else {
                ResultData<ReturnPayInfoVO> resultData = new ResultData<>();
                resultData.setResultCode(ResultCode.ORDER_STATUS_ERROR);
                return resultData;
            }
        }

        return new ResultData<>(null);
    }

    @Override
    public ResultData<BasePageResp<OrderPayVO>> getAnotherPayOrderPage(OrderPayReq req) {
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        req.setPayUserId(user.getId());
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<OrderPayVO> list = orderPayMapper.findAllPage(req);
        if (!list.isEmpty()) {
            List<Long> orderIds = list.stream().map(OrderPayVO::getOrderId).collect(Collectors.toList());
            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(OrderPayVO::getOrderUserId).collect(Collectors.toList()));
            Map<Long, Orders> ordersMap = daoService.getOrdersMap(orderIds);

            list.stream().forEach(item -> {
                item.setOrderUserNickname(userMap.get(item.getOrderUserId()).getNickname());
                item.setOrderUserAvatar(userMap.get(item.getOrderUserId()).getAvatar());
                item.setOrderTotalAmount(ordersMap.get(item.getOrderId()).getTotalPayAmount());
                item.setRefundAmount(ordersMap.get(item.getOrderId()).getTotalRefundAmount());
            });
        }
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public ResultData<RushOrderDetailVO> getRushOrderDetail(Long orderId) {
        RushOrderDetailVO detailVO = new RushOrderDetailVO();
        List<RushOrderVO> rushOrderVOList = new ArrayList<>();
        OrderSku orderSku = orderSkuMapper.findOneByOrderId(orderId);
        BeanUtils.copyProperties(orderSku, detailVO);
        List<OrderSku> orderSkuList = new ArrayList<>();
        if (RushBuyStatusEnum.PENDING.getStatus().equals(orderSku.getRushBuyStatus())) {
            orderSkuList = orderSkuMapper.findAllBySpuIdAndRushBuyStatus(orderSku.getSpuId(), RushBuyStatusEnum.PENDING.getStatus());
        } else if (RushBuyStatusEnum.SUCCESS.getStatus().equals(orderSku.getRushBuyStatus()) || RushBuyStatusEnum.FAIL.getStatus().equals(orderSku.getRushBuyStatus())) {
            orderSkuList = orderSkuMapper.findAllByRushBuyNo(orderSku.getRushBuyNo());
        }

        List<Long> collect = orderSkuList.stream().map(OrderSku::getUserId).collect(Collectors.toList());
        Map<Long, User> userMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(collect)) {
            userMap = daoService.getUserMap(collect);
        }
        Map<Long, User> finalUserMap = userMap;
        orderSkuList.stream().forEach(item -> {
            User user = finalUserMap.get(item.getUserId());
            RushOrderVO vo = new RushOrderVO();
            vo.setRushBuyStatus(item.getRushBuyStatus());
            vo.setUserNickname(user.getNickname());
            vo.setUserAvatar(user.getAvatar());
            vo.setUserId(item.getUserId());
            rushOrderVOList.add(vo);
        });
        detailVO.setRushOrderVOList(rushOrderVOList);
        List<RushSuccessVO> rushSuccess = orderSkuMapper.findRushSuccessLimit10();
        if (!rushSuccess.isEmpty()) {
            Map<Long, User> successUserMap = daoService.getUserMap(rushSuccess.stream().map(RushSuccessVO::getUserId).collect(Collectors.toList()));
            rushSuccess.stream().forEach(item -> {
                item.setPhone(SensitiveInfoUtil.mobilePhone(successUserMap.get(item.getUserId()).getUsername()));
            });
        }
        Sku sku = skuMapper.selectByPrimaryKey(orderSku.getSkuId());
        Orders orders = ordersMapper.selectByPrimaryKey(orderId);
        detailVO.setRushSuccessVOList(rushSuccess);
        detailVO.setImage(sku.getImage());
        detailVO.setOriginalPrice(sku.getOriginalPrice());
        detailVO.setTradeNo(orders.getTradeNo());
        return new ResultData<>(detailVO);
    }

    @Override
    public ResultData<BasePageResp<RushOrderResp>> getRushOrderPage(RushOrderReq req) {
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        req.setOrderKind(OrderKindEnum.COMMISSION.getKind());
        req.setUserId(user.getId());
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<RushOrderResp> list = orderSkuMapper.findAllRushPage(req);
        if (!list.isEmpty()) {
            List<OrderSku> endOrderSku = orderSkuMapper.findAllByRushBuyNoIn(list.stream().map(RushOrderResp::getRushBuyNo).collect(Collectors.toList()));
            Map<String, List<OrderSku>> endOrderSkuMap = new HashMap<>();
            if (!endOrderSku.isEmpty()) {
                endOrderSku.stream().forEach(item -> {
                    List<OrderSku> orderSkuList = endOrderSkuMap.get(item.getRushBuyNo());
                    if (orderSkuList == null) {
                        orderSkuList = new ArrayList<>();
                    }
                    if (orderSkuList.size() < 5) {
                        orderSkuList.add(item);
                        endOrderSkuMap.put(item.getRushBuyNo(), orderSkuList);
                    }
                });
            }

            List<OrderSku> pendingOrderSkuList = orderSkuMapper.findAllBySpuIdInAndRushBuyStatus(list.stream().map(RushOrderResp::getSpuId).collect(Collectors.toList()), RushBuyStatusEnum.PENDING.getStatus());
            Map<Long, List<OrderSku>> pendingOrderSkuMap = new HashMap<>();
            if (!pendingOrderSkuList.isEmpty()) {
                pendingOrderSkuList.stream().forEach(item -> {
                    List<OrderSku> orderSkuList = pendingOrderSkuMap.get(item.getSpuId());
                    if (orderSkuList == null) {
                        orderSkuList = new ArrayList<>();
                    }
                    if (orderSkuList.size() < 4) {
                        orderSkuList.add(item);
                        pendingOrderSkuMap.put(item.getSpuId(), orderSkuList);
                    }
                });
            }

            List<Long> userIds = new ArrayList<>();
            userIds.addAll(endOrderSku.stream().map(OrderSku::getUserId).collect(Collectors.toList()));
            userIds.addAll(pendingOrderSkuList.stream().map(OrderSku::getUserId).collect(Collectors.toList()));
            Map<Long, User> userMap = new HashMap<>();
            if (!CollectionUtils.isEmpty(userIds)) {
                userMap = daoService.getUserMap(userIds);
            }

            Map<Long, Sku> skuMap = daoService.getSkuMap(list.stream().map(RushOrderResp::getSkuId).collect(Collectors.toList()));
            Map<Long, Spu> spuMap = daoService.getSpuMap(list.stream().map(RushOrderResp::getSpuId).collect(Collectors.toList()));
            Map<Long, Orders> ordersMap = daoService.getOrdersMap(list.stream().map(RushOrderResp::getOrderId).collect(Collectors.toList()));

            Map<Long, User> finalUserMap = userMap;
            list.stream().forEach(item -> {
                item.setSpuImage(spuMap.get(item.getSpuId()).getMainImage());
                item.setOriginalPrice(skuMap.get(item.getSkuId()).getOriginalPrice());
                item.setTradeNo(ordersMap.get(item.getOrderId()).getTradeNo());
                List<OrderSku> orderSkuList = new ArrayList<>();
                if (RushBuyStatusEnum.PENDING.getStatus().equals(item.getRushBuyStatus())) {
                    orderSkuList = pendingOrderSkuMap.get(item.getSpuId());

                } else if (RushBuyStatusEnum.SUCCESS.getStatus().equals(item.getRushBuyStatus()) || RushBuyStatusEnum.FAIL.getStatus().equals(item.getRushBuyStatus())) {
                    orderSkuList = endOrderSkuMap.get(item.getRushBuyNo());
                }
                List<RushOrderVO> rushOrderVOList = new ArrayList<>();
                if (orderSkuList != null) {
                    orderSkuList.stream().forEach(orderSku -> {
                        User itemUser = finalUserMap.get(orderSku.getUserId());
                        if (itemUser != null) {
                            rushOrderVOList.add(RushOrderVO.builder().userNickname(itemUser.getNickname()).userAvatar(itemUser.getAvatar()).rushBuyStatus(orderSku.getRushBuyStatus()).userId(orderSku.getUserId()).build());
                        }
                    });
                }
                item.setRushOrderVOList(rushOrderVOList);
            });
        }
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public ResultData<BasePageResp<RushOrderSkuVO>> getRushOrderResultPage(RushOrderReq req) {
        req.setOrderKind(OrderKindEnum.COMMISSION.getKind());
        if (req.getRush_buy_status() == null) {
            req.setRush_buy_status(RushBuyStatusEnum.SUCCESS.getStatus());
        }
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<RushOrderSkuVO> list = orderSkuMapper.findRushOrderResultPage(req);
        if (!list.isEmpty()) {
            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(RushOrderSkuVO::getUserId).collect(Collectors.toList()));
            list.stream().forEach(item -> {
                item.setUserNickname(userMap.get(item.getUserId()).getNickname());
                item.setUserAvatar(userMap.get(item.getUserId()).getAvatar());
            });
        }
        return PageHelpUtil.buildPage(list, page);
    }
}